home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Language / Compiler / gencode.c < prev    next >
C/C++ Source or Header  |  1990-08-16  |  91KB  |  3,070 lines

  1. /*
  2.  * @(#)gencode.c    1.16  2/23/90
  3.  */
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <errno.h>
  7.  
  8. #include "assert.h"
  9. #include "addresses.h"
  10. #include "nodes.h"
  11. #include "map.h"
  12. #include "sequence.h"
  13. #include "system.h"
  14. #include "semantics.h"
  15. #include "builtins.h"
  16. #include "evaluate.h"
  17. #include "opNames.h"
  18. #include "primitives.h"
  19. #include "allocate.h"
  20. #include "MyParser.h"
  21. #include "datadesc.h"
  22. #include "environment.h"
  23. #include "regdefs.h"
  24. #include "genutils.h"
  25. #include "emit.h"
  26. #include "error.h"
  27. #include "consts.h"
  28. #include "flags.h"
  29. #include "trace.h"
  30. #include "option.h"
  31. #include "ecTypes.h"
  32. /*
  33.  * Imported routines
  34.  */
  35. extern void moveDataToRegister(), moveVariableToRegisters(), claimReg();
  36. extern void resolveGlobal();
  37. extern char *showInvoc(), *showExpression();
  38. extern void doPrimitive();
  39. extern Boolean isARealImport();
  40. extern NodePtr tryToExecuteAsAT();
  41.  
  42.  
  43. /*
  44.  * Global variables
  45.  */
  46.  
  47. extern Map manifestMap;
  48. extern int opNumber;
  49.  
  50. /*
  51.  * Exported definitions
  52.  */
  53. int nextLabelNumber = 101;
  54. int currentInstruction;
  55. OID currentCodeOID;
  56. int nextOperationNumber = 0;
  57. int nextObjectNumber = 0;
  58.  
  59. NodePtr currentObject = NULL, thisBuiltin = NULL;
  60.  
  61. /* measurement stuff */
  62. int             cEM_directCreates               = 0;
  63. int        cEM_totalInvokes        = 0;
  64. int             cEM_directInvokes               = 0;
  65. int             cEM_inlinedInvokes              = 0;
  66. int             cEM_localInvokes                = 0;
  67. int             cEM_selfInvokes                 = 0;
  68. int             cEM_KCTimmutableInvokes         = 0;
  69. int             cEM_UKCTimmutableInvokes        = 0;
  70. int             cEM_KCTresidentGlobalInvokes    = 0;
  71. int             cEM_UKCTresidentGlobalInvokes   = 0;
  72. int        cEM_moves            = 0;
  73. int        cEM_fixes            = 0;
  74. int        cEM_unfixes            = 0;
  75. int        cEM_refixes            = 0;
  76. int        cEM_locates            = 0;
  77. int        cEM_callByMoves            = 0;
  78. int        cEM_callByVisits        = 0;
  79. int        cEM_callByResultMoves        = 0;
  80.  
  81. /*
  82.  * Local definitions
  83.  */
  84.  
  85. #define USINGCONTINUE 1
  86. static Map ocMap;
  87. typedef enum { OC_Scheduled, OC_InProgress, OC_Done } OC_Stage;
  88. static NodePtr ocStack;
  89. static Boolean inObject = FALSE;
  90. static Boolean inMonitor = FALSE;
  91. static int nResultMoves = 0;
  92. /*
  93.  * Forward definitions
  94.  */
  95.  
  96. void generatePrimitive(), generateInvocation();
  97. void generateExpression(), generateExp(), generateUnaryExp();
  98. void generate(), generateTemplate(), generateVectorLiteral();
  99. void generateKnownConcreteTypeInvoke();
  100. void generateGlobalInvoke();
  101. void generateImmutableGlobalInvoke();
  102. void generateSelfInvoke();
  103. void generateMonInit();
  104. void generateMonEntry();
  105. void generateMonExit();
  106. void generateEnterOperation();
  107. void generateReturn();
  108. void generateCallC();
  109. void incMoveAndVisit();
  110. void generateMoveAndVisitMasks();
  111. void generateAssign();
  112. void generateAssignStat();
  113. void generateInitially();
  114. void generateProcess();
  115. void generateRecovery();
  116. void generateTemplate();
  117. void generateATObject();
  118. void generateCodeObject();
  119. void generateResultAbCons();
  120. void generateOneView();
  121. void generateArgumentViews();
  122. void ensureGenerate();
  123. void generateLocationRequest();
  124. void generate();
  125. void generateCode();
  126. DD generateCreation();
  127. static Boolean isMyAddress();
  128. Boolean isATrivialLiteral();
  129.  
  130. void generateInvocation(p, numResults, c)
  131. NodePtr p;
  132. int numResults;
  133. Context c;
  134. {
  135.   Variable *target;
  136.   Variable result;
  137.   int theOpNumber;
  138.   register NodePtr q, theObject;
  139.   register int i, nargs;
  140.   register NodePtr r, primno, opdef;
  141.   int opDefOpNumber, moveMask = 0, visitMask = 0;
  142.   NodePtr resultParam;
  143.   Symbol st;
  144.   NodePtr a, left, right;
  145.  
  146.   assert(p->tag == P_INVOC);
  147.   q = (NodePtr) Map_Lookup(manifestMap, (int) p);
  148.   if ((int) q != NIL) {
  149.     assert(numResults == 1);
  150.     q = (NodePtr) Map_Lookup(manifestMap, (int)p+1);
  151.     assert((int)q != NIL);
  152.     q = (NodePtr) Map_Lookup(manifestMap, (int)p+2);
  153.     assert((int)q != NIL);
  154.     assert(q->tag == P_OBLIT || q->tag == P_ATLIT);
  155.     assert(q->b.oblit.f.writeSeparately);
  156.     if (q->tag == P_OBLIT) {
  157.       result.abCon = buildAbConFromObject(q);
  158.       result.data.kind = DD_OIDToODP;
  159.       result.data.value.id = q->b.oblit.id;
  160.     } else {
  161.       result.abCon = buildConCon(SIGNATUREINDEX);
  162.       result.data.kind = DD_OIDToODP;
  163.       result.data.value.id = q->b.atlit.id;
  164.     }
  165.     vPush(result);
  166.     return;
  167.   }
  168.  
  169.   INCC(cEM_totalInvokes);
  170.   TS_StartInvocation();
  171.   generateExpression(p->b.invoc.target, anyContext);
  172.   target = vPeek(0);
  173.   if (isMyAddress(target->data)) {
  174.     q = currentObject;
  175.   } else {
  176.     q = getBestInfoFromAbCon(target->abCon);
  177.   }
  178.   theOpNumber = p->b.invoc.opNumber;
  179.  
  180.   if (q->tag == P_OBLIT) {
  181.     /*
  182.      * We actually know the "concrete type" of this reference, so we can
  183.      * optimize this invocation.
  184.      */
  185.     opdef = findObjectOperation(q, p->b.invoc.opname);
  186.     assert(opdef != NN);
  187.     assert(opdef->tag == P_OPDEF);
  188.     opDefOpNumber = opdef->b.opdef.opNumber;
  189.  
  190. #   define isGuaranteedLocal(p, q) \
  191.       ((OPTION(locals, 1) && (p->b.invoc.isLocal)) || \
  192.        (q)->b.oblit.f.immutable || \
  193.        (q) == currentObject)
  194.  
  195.     if (isGuaranteedLocal(p, q) && opdef->b.opdef.isInlineable) {
  196.       /*
  197.        * We inline the operation, and do either a primitive or an object
  198.        * creation, or if option(inline) then we try an assignment.
  199.        */
  200.       INCC(cEM_inlinedInvokes);
  201.       r = opdef->b.opdef.body;
  202.       assert(r->tag == P_BLOCK);
  203.       r = r->b.block.stats;
  204.       assert(isASequence(r));
  205.       assert(r->nChildren == 1);
  206.       ensureGenerate(q->b.oblit.codeOID);
  207.       if (r->b.children[0]->tag == P_PRIMSTAT) {
  208.     if (numResults == 1) {
  209.       resultParam = opdef->b.opdef.sig->b.opsig.results->b.children[0];
  210.       assert(resultParam->tag == P_PARAM);
  211.       st = resultParam->b.param.sym->b.symdef.symbol;
  212.       assert(st->tag == P_SYMBOL);
  213.       setDDAbstractType(c.v.abCon, getID(st->value.ATinfo));
  214.     }
  215.     primno = r->b.children[0]->b.primstat.number;
  216.     nargs = Sequence_Length(p->b.invoc.args);
  217.     assert (nargs <= 3);
  218.     if (nargs > 0) vForceToTemp(target, TS_PSL);
  219.     for (i = 0; i < nargs; i++) {
  220.       generateExpression(p->b.invoc.args->b.children[i], anyContext);
  221.       if (i < nargs - 1) vForceToTemp(vPeek(0), TS_PSL);
  222.     }
  223.     IFOPTION(comment, 2) 
  224.       Comment("\t\t\t\tInlined primitive %s", primno->b.intlit.string);
  225.     doPrimitive(q, p, primno, target, nargs,
  226.       (Boolean) (numResults == 1), c);
  227.       } else {
  228.     assert(r->b.children[0]->tag == P_ASSIGNSTAT);
  229.     theObject = r->b.children[0]->b.assignstat.right->b.children[0];
  230.     if (theObject->tag == P_OBLIT) {
  231.       /*
  232.        * We know that we can inline this operation, so we know that the
  233.        * initially of the object expects the same parameters and returns
  234.        * exactly one result, just like this operation.  We push the
  235.        * parameters onto the stack, and then do the object creation.
  236.        */
  237.       IFOPTION(comment, 1) Comment("\t\t\t\tInlined create operation (%s)",
  238.         OPTION(locals, 1) && p->b.invoc.isLocal ? "local" : "global");
  239.       assert(numResults == 1);
  240.       result.abCon = buildAbConFromObject(theObject);
  241.       /* allocate space for the result before the arguments */
  242.       IFOPTION(createonstack, 1 &&
  243.         theObject->b.oblit.codeOID != OIDOfBuiltin(B_INSTCT, STRINGINDEX)) {
  244.         emitMove(result.abCon, pusher, 'l');
  245.         emitMove(nilDD, pusher, 'l');
  246.       }
  247.       if (!(theObject->b.oblit.f.isVector ||
  248.         theObject->b.oblit.codeOID == OIDOfBuiltin(B_INSTCT, BITCHUNKINDEX) ||
  249.         theObject->b.oblit.codeOID == OIDOfBuiltin(B_INSTCT, STRINGINDEX))) {
  250.         for (i = 0; i < Sequence_Length(p->b.invoc.args); i++) {
  251.           vPush(pusherContext.v);
  252.           generateExpression(p->b.invoc.args->b.children[i], pusherContext);
  253.           vGenerateAssign();
  254.           TS_Push();
  255.         }
  256.       } else {
  257.         assert(Sequence_Length(p->b.invoc.args) == 1);
  258.         generateExpression(p->b.invoc.args->b.children[0], anyContext);
  259.         if (theObject->b.oblit.codeOID == OIDOfBuiltin(B_INSTCT, STRINGINDEX)) {
  260.           moveDataToRegister(vPeek(0), regs_arg1, DataBrand);
  261.         } else {
  262.           moveDataToRegister(vPeek(0), regs_arg2, DataBrand);
  263.         }
  264.         (void) vPop();
  265.       }
  266.       result.data = generateCreation(theObject, TRUE, 
  267.         (Boolean)(OPTION(locals, 1) && p->b.invoc.isLocal));
  268.       vPush(result);
  269.     } else {
  270.       /* this is an assignment with a single left and right */
  271.       IFOPTION(inline, 1) {
  272.         /*
  273.          * What we need to do is translate the addresses, probably force
  274.          * self into a register so that we can take care of the
  275.          * addressing, and worry about monitor entry.  If we discover 
  276.          * that we cannot perform the invoke, then goto doItForReal.
  277.          */
  278.         /*
  279.          * at this point, r is a pointer to the statements in the block
  280.          * of the operation definition.
  281.          */
  282.         a = r->b.children[0];
  283.         assert(a->tag == P_ASSIGNSTAT);
  284.         assert(Sequence_Length(a->b.assignstat.left) == 1);
  285.         assert(Sequence_Length(a->b.assignstat.right) == 1);
  286.         left = a->b.assignstat.left->b.children[0];
  287.         right = a->b.assignstat.right->b.children[0];
  288.         assert(left->tag == P_SYMREF);
  289.         if (right->tag == P_SYMREF || isATrivialLiteral(right)) {
  290.           goto doItForReal;
  291.         } else {
  292.           goto doItForReal;
  293.         }
  294.       } else {
  295.         goto doItForReal;
  296.       }
  297.     }
  298.       }
  299.       vDiscardN(numResults);            /* discard the target */
  300.       TS_EndInvocation();
  301.       return;
  302.     } else if (opDefOpNumber == -1) {
  303.       /* This is ownName */
  304.       vDiscard();
  305.       vPushOwnName(q);
  306.       return;
  307.     } else if (opDefOpNumber == -2) {
  308.       vDiscard();
  309.       vPushOwnType(q);
  310.       return;
  311.     }
  312.   }
  313.  
  314. doItForReal:
  315.  
  316.   if (theOpNumber < 0) {
  317.     /* this is ownName or ownType */
  318.     preemptKernelRegisters();
  319.     claimReg(regs_arg1, 1, ODPBrand);
  320.     result.data = buildRegisterDD(regs_arg1);
  321.     emitMove(target->abCon, result.data, 'l');
  322.     switch (theOpNumber) {
  323.       case -1:
  324.     generateKernelCall("em_ownName");
  325.     result.abCon = buildAbCon(OIDOfBuiltin(B_INSTAT, STRINGINDEX), 
  326.       OIDOfBuiltin(B_INSTCT, STRINGINDEX));
  327.     break;
  328.       case -2:
  329.     generateKernelCall("em_ownType");
  330.     result.abCon = buildAbCon(OIDOfBuiltin(B_INSTAT, ABSTRACTTYPEINDEX),
  331.       OIDOfBuiltin(B_INSTCT, SIGNATUREINDEX));
  332.     break;
  333.       default:
  334.     assert(FALSE);
  335.     break;
  336.     }
  337.     vDiscard();
  338.     vPush(result);
  339.     return;
  340.   }
  341.   generateMoveAndVisitMasks(p, &moveMask, &visitMask);
  342.   
  343.   vForceToTemp(target, TS_Stack | TS_PSL);
  344.   /*
  345.    * We know the ct if q is an oblit, but we have to generate a normal
  346.    * invocation of some sort.
  347.    */
  348.   
  349.   /* Results */
  350.   for (i = 0; i < numResults; i++) {
  351.     ddGenerateAssign(pusher, pusher, nilDD, nilDD);
  352.     TS_Results(8);
  353.   }
  354.   for (i = 0; i < Sequence_Length(p->b.invoc.args); i++) {
  355.     vPush(pusherContext.v);
  356.     generateExpression(p->b.invoc.args->b.children[i], pusherContext);
  357.     vGenerateAssign();
  358.     TS_Push();
  359.   }
  360.  
  361.   preemptKernelRegisters();
  362.   if (q->tag == P_ATLIT) {
  363.     assert(target->data.kind == DD_Address);
  364.     if (q->b.atlit.f.immutable) {
  365.       generateImmutableGlobalInvoke(p, target->data, target->abCon,
  366.     theOpNumber, moveMask, visitMask);
  367.     } else {
  368.       if (p->b.invoc.isLocal) 
  369.     if (!doGenerateCode) WarningMessage(p, "Local bit set incorrectly");
  370.       generateGlobalInvoke(p, target->data, target->abCon, theOpNumber,
  371.     moveMask, visitMask);
  372.     }
  373.   } else if (isMyAddress(target->data)) {
  374.     /* This is an invocation on myself, optimize it. */
  375.     /*
  376.      * TODO: We need to find the right opnumber, since the one we have (from
  377.      * p->b.invoc.opNumber) is appropriate for some abstract type.
  378.      */
  379.     TRACE1(atctsort, 3, "Trying to translate op %s",
  380.       ON_Name(p->b.invoc.opname->b.opname.id));
  381. #ifdef TRASHOPNUMBERS
  382.     theOpNumber = translateATOpNumberToCTOpNumber(target->abCon, theOpNumber);
  383.     assert(bflag || theOpNumber == opDefOpNumber);
  384. #endif
  385.     generateSelfInvoke(p, opDefOpNumber, moveMask, visitMask);
  386.   } else {
  387.     generateKnownConcreteTypeInvoke(p, q, target->data, target->abCon,
  388.       theOpNumber, p->b.invoc.opname, moveMask, visitMask, p->b.invoc.isLocal);
  389.   }
  390.   for(i = 0; i < numResults; i++) {
  391.     result.data = popper;
  392.     result.abCon = popper;
  393.     if (i == 0) setDDAbstractType(result.abCon, p->b.invoc.resultTypeOID);
  394.     vPush(result);
  395.   }
  396.   preemptKernelRegisters();
  397.   vDiscardN(numResults);            /* discard the target */
  398.   TS_EndInvocation();
  399. }
  400.  
  401. /*
  402.  * Generate code to branch to the label if the expression is the same as
  403.  * sense.
  404.  */
  405. void generateBranch(sense, label)
  406. Boolean sense;
  407. int label;
  408. {
  409.   Variable *bool;
  410.  
  411.   wroteCode = TRUE;
  412.   bool = vPeek(0);
  413.   vForceToTemp(bool, TS_Stack);
  414.   switch (bool->data.kind) {
  415.     case DD_Address:
  416.       emit("\ttstl\t%s\n", addressToString(bool->data.value.address));
  417.       if (sense) {
  418.     emit("\tj%s\tL_%d\n", JN(NEQ), label);
  419.       } else {
  420.     emit("\tj%s\tL_%d\n", JN(EQL), label);
  421.       }
  422.       break;
  423.     case DD_PSLCondition:
  424.       if (sense) {
  425.     emit("\t%sj%s\tL_%d\n", JF(bool->data.value.condition.isFloat), 
  426.       JN(bool->data.value.condition.psl), label);
  427.       } else {
  428.     emit("\t%sj%s\tL_%d\n",
  429.       JF(bool->data.value.condition.isFloat),
  430.       JN(negatedConditions[(int)bool->data.value.condition.psl]),
  431.       label);
  432.       }
  433.       break;
  434.     case DD_Manifest:
  435.       if (bool->data.value.manifest == sense) {
  436.     emit("\tj%s\tL_%d\n", JN(ALWAYS), label);
  437.       } else {
  438.     /* generate nothing */
  439.       }
  440.       break;
  441.     default:
  442.       assert(FALSE);
  443.       break;
  444.   }
  445.   vDiscard();
  446. }
  447.   
  448. void generateIfClause(p, endLabel, falseLabel)
  449. NodePtr p;
  450. int endLabel, falseLabel;
  451. {
  452.   lineNumberComment(p);
  453.   assert(p->tag == P_IFCLAUSE);
  454.   generateExpression(p->b.ifclause.exp, pslContext);
  455.   generateBranch(FALSE, falseLabel);
  456.   debugScope(1);
  457.   generate(p->b.ifclause.stats);
  458.   debugScope(0);
  459.   if (endLabel != 0) emit("\tj%s\tL_%d\n", JN(ALWAYS), endLabel);
  460. }
  461.  
  462. void initializeGenerate()
  463. {
  464.   assert(sizeof(ODTag) == sizeof(int));
  465.   nilNode = Construct(P_NILLIT, 0);
  466.   nilDD.kind = DD_Manifest;
  467.   nilDD.value.manifest = 0x80000000;
  468.  
  469.   nullDD = buildRegisterDD(500);
  470.  
  471.   pusher = nullDD;
  472.   pusher.kind = DD_Address;
  473.   nullDD.value.address = nullAddress;
  474.   pusher.value.address.autoDecrement = TRUE;
  475.   pusher.value.address.base = Stack;
  476.   pusher.value.address.offset = 0;
  477.  
  478.   popper = nullDD;
  479.   popper.kind = DD_Address;
  480.   nullDD.value.address = nullAddress;
  481.   popper.value.address.autoIncrement = TRUE;
  482.   popper.value.address.base = Stack;
  483.   popper.value.address.offset = 0;
  484.   
  485.   anyContext.kind = C_Any;
  486.   anyContext.v.data = nullDD;
  487.   anyContext.v.abCon = nullDD;
  488.   
  489.   pslContext.kind = C_PSL;
  490.   pslContext.v = anyContext.v;
  491.   
  492.   pusherContext.kind = C_Variable;
  493.   pusherContext.v.data = pusher;
  494.   pusherContext.v.abCon = pusher;
  495.  
  496.   ocMap = Map_Create();
  497.   ocStack = NULL;
  498. }
  499.  
  500. DD generateCreation(p, inlined, islocal)
  501. NodePtr p;
  502. Boolean inlined, islocal;
  503. {
  504.   DD resultData;
  505.   Variable nev, *numEntries = &nev, tcv, *tc = &tcv;
  506.   
  507.   int elementTypeSize;
  508.  
  509.   wroteCode = TRUE;
  510.   tc->data = nullDD;
  511.   tc->data.kind = DD_OIDToCodePtr;
  512.   tc->data.value.id = getCodeOID(p);
  513.   tc->abCon = buildAbConFromObject(p);
  514.   
  515.   if (p->b.oblit.codeOID == OIDOfBuiltin(B_INSTCT, STRINGINDEX)) {
  516.     preemptReg(regs_scratch, 1);
  517.     preemptReg(regs_arg2, 2);
  518.     if (inlined) {
  519.       numEntries->data = buildRegisterDD(regs_arg1);
  520.     } else {
  521.       numEntries->data = buildAddressDD(regs_l, firstParameterOffset);
  522.     }
  523.     numEntries->abCon = buildConCon(INTEGERINDEX);
  524.     
  525.     moveDataToRegister(numEntries, regs_arg1, DataBrand);
  526.     generateKernelCall("em_createString");
  527.     freeReg(regs_arg1, 1);
  528.     claimReg(regs_arg1, 1, ODPBrand);
  529.     resultData = buildRegisterDD(regs_arg1);
  530.   } else if (p->b.oblit.f.isVector) {
  531.     /*
  532.      * movl sizeInBytes, arg_2
  533.      * call em_globalCreateSized
  534.      */
  535.     if (p->b.oblit.codeOID == OIDOfBuiltin(B_INSTCT, BITCHUNKINDEX) ||
  536.         p->b.oblit.codeOID == OIDOfBuiltin(B_INSTCT, STRINGINDEX)) {
  537.       elementTypeSize = 1;
  538.     } else {
  539.       elementTypeSize = getSymbolSize(getElementTypeSymbol(p));
  540.     }
  541.     IFOPTION(comment, 1)
  542.       Comment("\t\t\t\t%sVector create %d bytes/element", 
  543.       p->b.oblit.f.immutable ? "Immutable " : "",
  544.       elementTypeSize);
  545.     if (elementTypeSize == 8) elementTypeSize = 3;
  546.     else if (elementTypeSize == 4) elementTypeSize = 2;
  547.     else if (elementTypeSize == 1) elementTypeSize = 0;
  548.     else assert(FALSE);
  549.     if (inlined) {
  550.       numEntries->data = buildRegisterDD(regs_arg2);
  551.     } else {
  552.       numEntries->data = buildAddressDD(regs_l, firstParameterOffset);
  553.     }
  554.     numEntries->abCon = buildConCon(INTEGERINDEX);
  555.     
  556.     moveDataToRegister(numEntries, regs_arg2, DataBrand);
  557.     moveDataToRegister(tc, regs_arg1, ODPBrand);
  558.     preemptReg(regs_scratch, 1);
  559.     claimReg(regs_arg3, 1, DataBrand);
  560. #ifdef vax
  561.     emit("\tsubl3\t$ 1,%s,%s\n", RN(regs_arg2), RN(regs_arg3));
  562. #endif
  563. #ifdef sun
  564.     emitMove(buildRegisterDDNC(regs_arg2), buildRegisterDDNC(regs_arg3), 'l');
  565.     emit("\tsubql\t#1,%s\n", RN(regs_arg3));
  566. #endif
  567.     if (elementTypeSize != 0)
  568. #ifdef vax
  569.       emit("\tashl\t$ %d,%s,%s\n", elementTypeSize, RN(regs_arg2), RN(regs_arg2));
  570. #endif
  571. #ifdef sun
  572.       emit("\tasll\t#%d,%s\n", elementTypeSize, RN(regs_arg2));
  573. #endif
  574.     if (OPTION(locals, 1) && islocal) {
  575.       generateKernelCall("em_localCreateVector");
  576.     } else if (p->b.oblit.f.immutable) {
  577.       generateKernelCall("em_localCreateVector");
  578.     } else {
  579.       generateKernelCall("em_globalCreateVector");
  580.     }
  581.     FREEV(tc);
  582.     FREEV(numEntries);
  583.     freeReg(regs_arg3, 1);
  584.     claimReg(regs_arg1, 1, ODPBrand);
  585.     resultData = buildRegisterDD(regs_arg1);
  586.     IFOPTION(createonstack, 1) {
  587.       emitMove(popper, resultData, 'l');
  588.       emit(POPABCON);
  589.     }
  590.   } else if (p->b.oblit.f.immutable || (OPTION(locals, 1) && islocal)) {
  591.     /* call local create */
  592.     IFOPTION(comment, 1) Comment("\t\t\t\t%s create",
  593.       p->b.oblit.f.immutable ? "Immutable" : "Local mutable");
  594.     assert(!p->b.oblit.f.isVector);
  595.     moveDataToRegister(tc, regs_arg1, ODPBrand);
  596.     preemptReg(regs_scratch, 1);
  597.     preemptReg(regs_arg2, 2);
  598.     generateKernelCall("em_localCreate");
  599.     FREEV(tc);
  600.     claimReg(regs_arg1, 1, ODPBrand);
  601.     resultData = buildRegisterDD(regs_arg1);
  602.     IFOPTION(createonstack, 1) {
  603.       emitMove(popper, resultData, 'l');
  604.       emit(POPABCON);
  605.     }
  606.   } else {
  607.     IFOPTION(comment, 1) Comment("\t\t\t\tGlobal create");
  608.     moveDataToRegister(tc, regs_arg1, ODPBrand);
  609.     preemptReg(regs_scratch, 1);
  610.     preemptReg(regs_arg2, 2);
  611.     generateKernelCall("em_globalCreate");
  612.     FREEV(tc);
  613.     claimReg(regs_arg1, 1, ODPBrand);
  614.     resultData = buildRegisterDD(regs_arg1);
  615.     IFOPTION(createonstack, 1) {
  616.       emitMove(popper, resultData, 'l');
  617.       emit(POPABCON);
  618.     }
  619.   }
  620.   return(resultData);
  621. }
  622.  
  623. #define doChildren(p) {\
  624.   Sequence_For(child, p)\
  625.     if (child != NULL) generate(child);\
  626.   Sequence_Next\
  627. }
  628.  
  629. static Boolean isMyAddress(d)
  630. DD d;
  631. {
  632.   return(d.kind == DD_Self);
  633. }
  634.  
  635. void generateKnownConcreteTypeInvoke(p, theCode,
  636.       target, targetAbCon, opNumber, opname, moveMask, visitMask, isLocal)
  637. NodePtr p;
  638. NodePtr theCode;
  639. DD target, targetAbCon;
  640. int opNumber;
  641. NodePtr opname;
  642. int moveMask, visitMask;
  643. Boolean isLocal;
  644. {
  645.   NodePtr theOpDef;
  646.   int opDefOpNumber;
  647.  
  648.   wroteCode = TRUE;
  649.   theOpDef = findObjectOperation(theCode, opname);
  650.   assert(theOpDef->tag == P_OPDEF);
  651.   opDefOpNumber = theOpDef->b.opdef.opNumber;
  652.   assert(targetAbCon.kind == DD_AbCon);
  653.   if (opNumber != opDefOpNumber) {
  654.     TRACE3(atctsort, 1, "Invocation: %s, opNumber = %d, opDefOpNumber = %d",
  655.       showInvoc(p), opNumber, opDefOpNumber);
  656.   }
  657.   if (theCode->b.oblit.f.immutable) {
  658.     INC(cEM_KCTimmutableInvokes);
  659.     IFOPTION(comment, 1)
  660.       Comment("\t\t\t\tKCTimmutableInvoke (%s)", showInvoc(p));
  661.     incMoveAndVisit(moveMask, visitMask);
  662.     ddGenerateAssign(
  663.       pusher,
  664.       pusher,
  665.       buildRegisterDDNC(regs_g),
  666.       buildRegisterDDNC(regs_l));
  667.     emitMove(buildRegisterDDNC(regs_b), pusher, 'l');
  668.     /*
  669.      * Since this object is immutable, we can invoke it directly.
  670.      */
  671.     emitMove(target, buildRegisterDDNC(regs_g), 'l');
  672.     JUMPDEBUG();
  673.     emitMove(buildRegisterDDNC(regs_sp), buildRegisterDDNC(regs_l), 'l');
  674.     currentInstruction = nextLabelNumber++;
  675.     emit("L_%d:\tj%s\t%s0xabcdef01\n", currentInstruction,
  676.       JN(SUBR), GLOBALVARINDICATOR);
  677.     JUMPCHECK();
  678.     if (targetAbCon.kind == DD_AbCon) {
  679.       assert(getDDConcreteType(targetAbCon) == theCode->b.oblit.codeOID);
  680.     }
  681.     ensureGenerate(theCode->b.oblit.codeOID);
  682.     saveRelocationInfo(currentInstruction, 2, AR_OpNumberToAddress,
  683.       theCode->b.oblit.codeOID, (OID)opDefOpNumber);
  684.   } else if (OPTION(locals, 1) && isLocal) {
  685.     INC(cEM_localInvokes);
  686.     IFOPTION(comment, 1)
  687.       Comment("\t\t\t\tlocalInvoke (%s)", showInvoc(p));
  688.     incMoveAndVisit(moveMask, visitMask);
  689.     ddGenerateAssign(
  690.       pusher,
  691.       pusher,
  692.       buildRegisterDDNC(regs_g),
  693.       buildRegisterDDNC(regs_l));
  694.     emitMove(buildRegisterDDNC(regs_b), pusher, 'l');
  695.     /*
  696.      * Since this object is guaranteed local, we can invoke it directly.
  697.      */
  698.     emitMove(target, buildRegisterDDNC(regs_g), 'l');
  699.     if (gdflag) {
  700.       emitBranchOnBit(ODTag_global, 'c', regs_g, buildLabelDD(6));
  701.       emitMove(buildRegisterDDNC(regs_g), buildRegisterDDNC(regs_arg1), 'l');
  702.       emitMove(targetAbCon, buildRegisterDDNC(regs_arg2), 'l');
  703.       emitMove(nilDD, buildRegisterDDNC(regs_arg3), 'l');
  704.       emitMove(buildRegisterDDNC(regs_sp), buildRegisterDDNC(regs_l), 'l');
  705.       generateKernelCall("em_invokeAssumptionFailure");
  706.       emit("6:\n");
  707.     }
  708.     JUMPDEBUG();
  709.     emitMove(buildRegisterDDNC(regs_sp), buildRegisterDDNC(regs_l), 'l');
  710.     currentInstruction = nextLabelNumber++;
  711.     emit("L_%d:\tj%s\t%s0xabcdef01\n", currentInstruction,
  712.       JN(SUBR), GLOBALVARINDICATOR);
  713.     JUMPCHECK();
  714.     if (targetAbCon.kind == DD_AbCon) {
  715.       assert(getDDConcreteType(targetAbCon) == theCode->b.oblit.codeOID);
  716.     }
  717.     ensureGenerate(theCode->b.oblit.codeOID);
  718.     saveRelocationInfo(currentInstruction, 2, AR_OpNumberToAddress,
  719.       theCode->b.oblit.codeOID, (OID)opDefOpNumber);
  720.   } else {
  721.     IFOPTION(comment, 1) Comment("\t\t\t\tKCTresidentGlobalInvoke (%s)",
  722.       showInvoc(p));    
  723.     /* I know the ct, so I know that it is not immutable and not direct */
  724.     incMoveAndVisit(moveMask, visitMask);
  725.     ddGenerateAssign(
  726.       pusher,
  727.       pusher,
  728.       buildRegisterDDNC(regs_g),
  729.       buildRegisterDDNC(regs_l));
  730.     emitMove(buildRegisterDDNC(regs_b), pusher, 'l');
  731.     emitMove(target, buildRegisterDDNC(regs_b), 'l');
  732.     if (gdflag) {
  733.       emitBranchOnBit(ODTag_global, 's', regs_b, buildLabelDD(6));
  734.       emitMove(nilDD, buildRegisterDDNC(regs_arg1), 'l');
  735.       emitMove(targetAbCon, buildRegisterDDNC(regs_arg2), 'l');
  736.       emitMove(buildRegisterDDNC(regs_b), buildRegisterDDNC(regs_arg3), 'l');
  737.       emitMove(buildRegisterDDNC(regs_sp), buildRegisterDDNC(regs_l), 'l');
  738.       generateKernelCall("em_invokeAssumptionFailure");
  739.       emit("6:\n");
  740.     }
  741.     emitBranchOnBit(ODTag_frozen, 'c', regs_b, buildLabelDD(1));
  742.     /*
  743.      * We have to use the opNumber, which is from the abstract type, even
  744.      * though if we find it local we will be invoking a different operation.
  745.      * This is because we know the concrete type, but if we invoke this
  746.      * through the kernel, it will be using the ab/con (really the con/con),
  747.      * which does not include operations that are not exported.
  748.      */
  749.     emitMove(buildManifestDD(opNumber), buildRegisterDDNC(regs_arg1), 'l');
  750.     emitMove(targetAbCon, buildRegisterDDNC(regs_arg2), 'l');
  751.     emitMove(buildLabelDD(2), pusher, 'l');
  752.     JUMPDEBUG();
  753.     if (moveMask != 0 || visitMask != 0) {
  754.       ddGenerateAssign(pusher, pusher, buildManifestDD(visitMask),
  755.     buildManifestDD(moveMask));
  756.       emit("\tjmp\t%s_em_invokeWithMove\n", GLOBALVARINDICATOR);
  757.     } else {
  758.       emit("\tjmp\t%s_em_invoke\n", GLOBALVARINDICATOR);
  759.     }
  760.     emit("1:\n");
  761.     emitMove(buildAddressDD(regs_b, GOD_dataPtr), buildRegisterDDNC(regs_g), 'l');
  762.     JUMPDEBUG();
  763.     emitMove(buildRegisterDDNC(regs_sp), buildRegisterDDNC(regs_l), 'l');
  764.     INC(cEM_KCTresidentGlobalInvokes);
  765.     currentInstruction = nextLabelNumber++;
  766.     emit("L_%d:\tj%s\t%s0xabcdef01\n", currentInstruction, JN(SUBR), GLOBALVARINDICATOR);
  767.     if (targetAbCon.kind == DD_AbCon) {
  768.       assert(getDDConcreteType(targetAbCon) == theCode->b.oblit.codeOID);
  769.     }
  770.     saveRelocationInfo(currentInstruction, 2, AR_OpNumberToAddress,
  771.       theCode->b.oblit.codeOID, (OID)opDefOpNumber);
  772.     emit("2:\n");
  773.     JUMPCHECK();
  774.   }
  775. }
  776.  
  777. void generateGlobalInvoke(p, target, targetAbCon, theOpNumber, moveMask,
  778.   visitMask)
  779. NodePtr p;
  780. DD target, targetAbCon;
  781. int theOpNumber, moveMask, visitMask;
  782. {
  783.   wroteCode = TRUE;
  784.   IFOPTION(comment, 1) Comment("\t\t\t\tUKCTresidentGlobalInvoke (%s)",
  785.     showInvoc(p));
  786.   incMoveAndVisit(moveMask, visitMask);
  787.   ddGenerateAssign(
  788.     pusher,
  789.     pusher,
  790.     buildRegisterDDNC(regs_g),
  791.     buildRegisterDDNC(regs_l));
  792.   emitMove(buildRegisterDDNC(regs_b), pusher, 'l');
  793.   emitMove(targetAbCon, buildRegisterDDNC(regs_scratch), 'l');
  794.   emitBranchOnBit(ODTag_frozen, 'c', regs_scratch, buildLabelDD(9));
  795.   emitMove(target, buildRegisterDDNC(regs_b), 'l');
  796.   if (gdflag) {
  797.     emitBranchOnBit(ODTag_global, 's', regs_b, buildLabelDD(6));
  798.     emitMove(nilDD, buildRegisterDDNC(regs_arg1), 'l');
  799.     emitMove(buildRegisterDDNC(regs_scratch), buildRegisterDDNC(regs_arg2), 'l');
  800.     emitMove(buildRegisterDDNC(regs_b), buildRegisterDDNC(regs_arg3), 'l');
  801.     emitMove(buildRegisterDDNC(regs_sp), buildRegisterDDNC(regs_l), 'l');
  802.     generateKernelCall("em_invokeAssumptionFailure");
  803.     emit("6:\n");
  804.   }
  805.   emitBranchOnBit(ODTag_frozen, 'c', regs_b, buildLabelDD(1));
  806.   emitMove(buildManifestDD(theOpNumber), buildRegisterDDNC(regs_arg1), 'l');
  807.   emitMove(buildRegisterDDNC(regs_scratch), buildRegisterDDNC(regs_arg2), 'l');
  808.   emitMove(buildLabelDD(2), pusher, 'l');
  809.   JUMPDEBUG();
  810.   if (moveMask != 0 || visitMask != 0) {
  811.     ddGenerateAssign(pusher, pusher, buildManifestDD(visitMask),
  812.       buildManifestDD(moveMask));
  813.     emit("\tjmp\t%s_em_invokeWithMove\n", GLOBALVARINDICATOR);
  814.   } else {
  815.     emit("\tjmp\t%s_em_invoke\n", GLOBALVARINDICATOR);
  816.   }
  817.   emit("9:\n");
  818.   emitMove(target, buildRegisterDDNC(regs_g), 'l');
  819.   emit("\tj%s\t5f\n", JN(ALWAYS));
  820.   emit("1:\n");
  821.   emitMove(buildAddressDD(regs_b, GOD_dataPtr), buildRegisterDDNC(regs_g), 'l');
  822.   emit("5:");
  823.   JUMPDEBUG();
  824.   emitMove(buildRegisterDDNC(regs_sp), buildRegisterDDNC(regs_l), 'l');
  825.   INC(cEM_UKCTresidentGlobalInvokes);
  826.   assert(theOpNumber >= 0);
  827. #ifdef vax
  828.   emit("\tj%s\t* %d+%d(%s)\n", JN(SUBR), AbCon_opVector,
  829.     theOpNumber * sizeof_AbConOpVectorEntry, RN(regs_scratch));
  830. #endif
  831. #ifdef sun
  832.   emitMove(buildAddressDD(regs_scratch,
  833.          AbCon_opVector + theOpNumber * sizeof_AbConOpVectorEntry),
  834.     buildRegisterDDNC(regs_scratch), 'l');
  835.   emit("\tj%s\t%s@\n", JN(SUBR), RN(regs_scratch));
  836. #endif
  837.   emit("2:\n");
  838.   JUMPCHECK();
  839. }
  840.  
  841. void generateImmutableGlobalInvoke(p, target, targetAbCon, theOpNumber,
  842.   moveMask, visitMask)
  843. NodePtr p;
  844. DD target, targetAbCon;
  845. int theOpNumber, moveMask, visitMask;
  846. {
  847.   wroteCode = TRUE;
  848.   INC(cEM_UKCTimmutableInvokes);
  849.   IFOPTION(comment, 1) Comment("\t\t\t\tUKCTimmutableInvoke (%s)",
  850.     showInvoc(p));
  851.   incMoveAndVisit(moveMask, visitMask);
  852.   ddGenerateAssign(
  853.     pusher,
  854.     pusher,
  855.     buildRegisterDDNC(regs_g),
  856.     buildRegisterDDNC(regs_l));
  857.   emitMove(buildRegisterDDNC(regs_b), pusher, 'l');
  858.   emitMove(targetAbCon, buildRegisterDDNC(regs_scratch), 'l');
  859.   /*
  860.    * Since this object is immutable, we can invoke it directly.
  861.    */
  862.   emitMove(target, buildRegisterDDNC(regs_g), 'l');
  863.   if (gdflag) {
  864.     emitBranchOnBit(ODTag_frozen, 'c', regs_scratch, buildLabelDD(6));
  865.     emitBranchOnBit(ODTag_replicated, 's', regs_g, buildLabelDD(6));
  866.     emitMove(buildRegisterDDNC(regs_g), buildRegisterDDNC(regs_arg1), 'l');
  867.     emitMove(buildRegisterDDNC(regs_scratch), buildRegisterDDNC(regs_arg2),
  868.       'l');
  869.     emitMove(nilDD, buildRegisterDDNC(regs_arg3), 'l');
  870.     emitMove(buildRegisterDDNC(regs_sp), buildRegisterDDNC(regs_l), 'l');
  871.     generateKernelCall("em_invokeAssumptionFailure");
  872.     emit("6:\n");
  873.   }
  874.   JUMPDEBUG();
  875.   emitMove(buildRegisterDDNC(regs_sp), buildRegisterDDNC(regs_l), 'l');
  876. #ifdef vax
  877.   emit("\tj%s\t* %d+%d(%s)\n", JN(SUBR), AbCon_opVector,
  878.     theOpNumber * sizeof_AbConOpVectorEntry, RN(regs_scratch));
  879. #endif
  880. #ifdef sun
  881.   emitMove(buildAddressDD(regs_scratch,
  882.          AbCon_opVector + theOpNumber * sizeof_AbConOpVectorEntry),
  883.     buildRegisterDDNC(regs_scratch), 'l');
  884.   emit("\tj%s\t%s@\n", JN(SUBR), RN(regs_scratch));
  885. #endif
  886.   JUMPCHECK();
  887. }
  888.  
  889. /*ARGSUSED*/
  890. void generateSelfInvoke(p, theOpNumber, moveMask, visitMask)
  891. NodePtr p;
  892. int theOpNumber, moveMask, visitMask;
  893. {
  894.   wroteCode = TRUE;
  895.   INC(cEM_selfInvokes);
  896.   IFOPTION(comment, 1) Comment("\t\t\t\tselfInvoke (%s)", showInvoc(p));
  897.   incMoveAndVisit(moveMask, visitMask);
  898.   ddGenerateAssign(
  899.     pusher,
  900.     pusher,
  901.     buildRegisterDDNC(regs_g),
  902.     buildRegisterDDNC(regs_l));
  903.   emitMove(buildRegisterDDNC(regs_b), pusher, 'l');
  904.   JUMPDEBUG();
  905.   emitMove(buildRegisterDDNC(regs_sp), buildRegisterDDNC(regs_l), 'l');
  906.   emit("\tj%s\tL_operationEP_%d\n", JN(SUBR), theOpNumber);
  907.   JUMPCHECK();
  908. }
  909.  
  910. void generateMonInit()
  911. {
  912.   DD mon, zero;
  913.   int offset =
  914.     firstInstanceOffset+(currentObject->b.oblit.f.immutable ? 4 : 0);
  915.   assert(currentObject->b.oblit.monitor != NN);
  916.   if (currentObject->b.oblit.monitor->b.monitor.mayBeElided) return;
  917.   zero = buildManifestDD(0);
  918.   mon = buildAddressDD(regs_g, offset);
  919.   ddGenerateAssign(mon, nextAddress(mon), zero, zero);
  920. }
  921.  
  922. void generateMonEntry()
  923. {
  924.   int offset =
  925.     firstInstanceOffset+(currentObject->b.oblit.f.immutable ? 4 : 0);
  926.   assert(currentObject->b.oblit.monitor != NN);
  927.   if (currentObject->b.oblit.monitor->b.monitor.mayBeElided) return;
  928. #ifdef vax
  929.   emit("\tbbcs\t$0,%d(%s),1f\n", offset, RN(regs_g));
  930. #endif
  931. #ifdef sun
  932.   emit("\tbset\t#0,%s@(%d)\n", RN(regs_g), offset + 3);
  933.   emit("\tb%s\t1f\n", JN(EQL));
  934. #endif
  935.   emitMoveAddress(buildAddressDD(regs_g, offset),buildRegisterDDNC(regs_arg1));
  936.   generateKernelCall("em_monEntry");
  937.   emit("1:\n");
  938. }
  939.   
  940. void generateMonExit()
  941. {
  942.   int offset =
  943.     firstInstanceOffset+(currentObject->b.oblit.f.immutable ? 4 : 0);
  944.   assert(currentObject->b.oblit.monitor != NN);
  945.   if (currentObject->b.oblit.monitor->b.monitor.mayBeElided) return;
  946. #define NEWVERSION
  947. #ifdef NEWVERSION
  948.   emit("\ttstl\t");
  949.   writeDD(buildAddressDD(regs_g, offset + sizeof(int)), '\n');
  950.   emit("\tj%s\t1f\n", JN(EQL));
  951. #endif
  952.   emitMoveAddress(buildAddressDD(regs_g, offset),buildRegisterDDNC(regs_arg1));
  953.   generateKernelCall("em_monExit");
  954. #ifdef NEWVERSION
  955.   emit("\tj%s\t2f\n", JN(ALWAYS));
  956.   emit("1:");
  957.   emitMove(buildManifestDD(0), buildAddressDD(regs_g, offset), 'l');
  958.   emit("2:\n");
  959. #endif
  960. }
  961.  
  962. void generateEnterOperation(localSize, maxStack)
  963. int localSize, maxStack;
  964. {
  965.   IFOPTION(comment, 1) 
  966.     Comment("\t\t\t\tEnterOperation(%d, %d)", localSize, maxStack);
  967.   emitMoveAddress(buildAddressDD(regs_sp, -maxStack),
  968.     buildRegisterDDNC(regs_scratch));
  969.   emit("\tcmpl\t%s_splimit,", GLOBALVARINDICATOR);
  970.   writeDD(buildRegisterDDNC(regs_scratch), '\n');
  971. #ifdef vax
  972.   emit("\tb%s\t1f\n", JN(LEQU));
  973. #endif
  974. #ifdef sun
  975.   emit("\tb%s\t1f\n", JN(GTRU));
  976. #endif
  977.   emitMove(buildManifestDD(maxStack), buildRegisterDDNC(regs_arg1), 'l');
  978.   generateKernelCall("em_stackCheck");
  979.   emit("1:\n");
  980.   emitMove(buildRegisterDDNC(regs_ssp), pusher, 'l');
  981.   localSize -= 4;
  982.   IFOPTION(nilspace, 1) {
  983.     if (localSize > 0) {
  984.       emitMove(nilDD, buildRegisterDDNC(regs_arg2), 'l');
  985.       emitMove(buildManifestDD((localSize/4) - 1), buildRegisterDDNC(regs_arg3), 'l');
  986.       emit("1:");
  987.       emitMove(buildRegisterDDNC(regs_arg2), pusher, 'l');
  988. #ifdef vax
  989.       emit("\tsobgeq\t");
  990. #endif
  991. #ifdef sun
  992.       emit("\tdbf\t");
  993. #endif
  994.       writeDD(buildRegisterDDNC(regs_arg3), ',');
  995.       writeLabel(buildLabelDD(-1), '\n');
  996.     }
  997.   } else IFOPTION(nilspace, 2) {
  998. #ifdef vax
  999.     emit("\tsubl2\t$%d, sp\n", localSize);
  1000. #endif
  1001. #ifdef sun
  1002.     emit("\taddw\t#%d, sp\n", -localSize);
  1003. #endif
  1004.   } else assert(FALSE);
  1005. }
  1006.  
  1007. void generateReturn(paramBytes)
  1008. int paramBytes;
  1009. {
  1010.   wroteCode = TRUE;
  1011.   IFOPTION(comment, 1) Comment("\t\t\t\treturn(%d)", paramBytes);
  1012.   IFOPTION(invokequeue, 1) {
  1013.     emit("\ttstl\t");
  1014.     writeDD(buildAddressDD(regs_l, -8), '\n');
  1015.     emit("\tj%s\t1f\n", JN(GTR));
  1016. #ifdef vax
  1017.     emit("\tremque\t-%d(%s),%s\n", 
  1018.       firstLocalOffset+sizeof(InvokeQueue), RN(regs_l), RN(regs_scratch));
  1019. #endif
  1020. #ifdef sun
  1021.     {
  1022.       DD F, B, T, O;
  1023.       F = buildAddressDD(regs_l, -(firstLocalOffset + sizeof(InvokeQueue)));
  1024.       B = nextAddress(F);
  1025.       T = buildRegisterDDNC(regs_scratch);
  1026.       emitMove(F, T, 'l');
  1027.       O = buildAddressDD(regs_scratch, 4);
  1028.       emitMove(B, O, 'l');
  1029.       emitMove(B, T, 'l');
  1030.       O = buildAddressDD(regs_scratch, 0);
  1031.       emitMove(F, O, 'l');
  1032.     }
  1033. #endif
  1034.     emit("1:\n");
  1035.   } else IFOPTION(invokequeue, 2) {
  1036. #ifdef vax
  1037.     emit("\tremque\t-%d(%s),%s\n", 
  1038.       firstLocalOffset+sizeof(InvokeQueue), RN(regs_l), RN(regs_scratch));
  1039. #endif
  1040. #ifdef sun
  1041.     Comment("Queue remove!!!!!");
  1042. #endif
  1043.   } else {
  1044.     assert(FALSE);
  1045.   }
  1046.   emitMoveAddress(buildAddressDD(regs_l, -4), buildRegisterDDNC(regs_sp));
  1047.   emitMove(popper, buildRegisterDDNC(regs_scratch), 'l');
  1048.   emitMove(popper, buildRegisterDDNC(regs_b), 'l');
  1049.   ddGenerateAssign(
  1050.     buildRegisterDDNC(regs_g),
  1051.     buildRegisterDDNC(regs_l),
  1052.     popper,
  1053.     popper);
  1054.   if (paramBytes != 0) {
  1055. #ifdef vax
  1056.     emit("\taddl2\t");
  1057. #endif
  1058. #ifdef sun
  1059.     emit("\tadd%sw\t", inRange(paramBytes, 0, 8) ? "q" : "");
  1060. #endif
  1061.     writeDD(buildManifestDD(paramBytes), ',');
  1062.     writeDD(buildRegisterDDNC(regs_sp), '\n');
  1063.   }
  1064.   if (gdflag) emit(SETLASTJUMPFROM);
  1065.   emit("\tjmp\t");
  1066.   writeDD(buildAddressDD(regs_scratch, 0), '\n');
  1067. }
  1068.  
  1069. void generateCallC(n, name, isExpression)
  1070. int n;
  1071. char *name;
  1072. Boolean isExpression;
  1073. {
  1074.   DD mover;
  1075.   int reg;
  1076.   wroteCode = TRUE;
  1077.   IFOPTION(comment, 1) Comment("\t\t\t\tCallC $%d,%s", n, name);
  1078. #ifdef sun
  1079.   emitMove(buildRegisterDDNC(regs_ssp), buildRegisterDDNC(regs_scratch), 'l');
  1080.   emitMoveAddress(buildAddressDD(regs_scratch, SS_regs),
  1081.     buildRegisterDDNC(regs_scratch));
  1082. #endif
  1083. #ifdef vax
  1084.   emitMoveAddress(buildAddressDD(regs_ssp, SS_regs),
  1085.     buildRegisterDDNC(regs_scratch));
  1086. #endif
  1087.   mover = popper;
  1088.   mover.value.address.base = regs_scratch;
  1089.   setDDAbstractType(mover, OIDOfBuiltin(B_INSTAT, INTEGERINDEX));
  1090.   emitMove(buildRegisterDDNC(4), mover, 'l');
  1091.   for (reg = 5; reg <= 14; reg += 2) {
  1092.     ddGenerateAssign(
  1093.       mover,
  1094.       mover,
  1095.       buildRegisterDDNC(reg),
  1096.       buildRegisterDDNC(reg+1));
  1097.   }
  1098. #ifdef OLDCPRIM
  1099.   emit("\tmovl\t%s_kernelsp,sp\n", GLOBALVARINDICATOR);
  1100.   if (n >= 3) emitMove(buildRegisterDDNC(regs_arg3), pusher, 'l');
  1101.   if (n >= 2) emitMove(buildRegisterDDNC(regs_arg2), pusher, 'l');
  1102.   if (n >= 1) emitMove(buildRegisterDDNC(regs_arg1), pusher, 'l');
  1103. #else
  1104.   emit("\tmovl\t%s,sp\n", RN(regs_arg1));
  1105. #endif
  1106. #ifdef vax
  1107.   emit("\tcalls\t$%d,*$ _%s\n", n, name);
  1108. #endif
  1109. #ifdef sun
  1110.   emit("\tj%s\t_%s\n", JN(SUBR), name);
  1111.   if (n > 0) emit("\tadd%sw\t#%d,sp\n", n <= 2 ? "q" : "", n * 4);
  1112. #endif
  1113.   if (isExpression) {
  1114.     emitMove(buildRegisterDDNC(regs_cresult),buildRegisterDDNC(regs_arg1),'l');
  1115.   }
  1116.   emit("\tmovl\t%s_currentSSP,%s\n", GLOBALVARINDICATOR, RN(regs_ssp));
  1117. #ifdef sun
  1118.   emitMove(buildRegisterDDNC(regs_ssp), buildRegisterDDNC(regs_scratch), 'l');
  1119.   emitMoveAddress(buildAddressDD(regs_scratch, SS_regs),
  1120.     buildRegisterDDNC(regs_scratch));
  1121. #endif
  1122. #ifdef vax
  1123.   emitMoveAddress(buildAddressDD(regs_ssp, SS_regs),
  1124.     buildRegisterDDNC(regs_scratch));
  1125. #endif
  1126.   emitMove(mover, buildRegisterDDNC(4), 'l');
  1127.   for (reg = 5; reg <= 14; reg += 2) {
  1128.     ddGenerateAssign(
  1129.       buildRegisterDDNC(reg),
  1130.       buildRegisterDDNC(reg+1),
  1131.       mover,
  1132.       mover);
  1133.   }
  1134. }
  1135.  
  1136. void incMoveAndVisit(moveMask, visitMask)
  1137. int moveMask, visitMask;
  1138. {
  1139.   register int i;
  1140.   if (! (gmflag && doGenerateCode)) return;
  1141.   for (i = 0; i < 32; i++) {
  1142.     if (moveMask & (1 << i)) INC(cEM_callByMoves);
  1143.     if (visitMask & (1 << i)) INC(cEM_callByVisits);
  1144.   }
  1145. }
  1146.  
  1147. void generateMoveAndVisitMasks(p, moveMask, visitMask)
  1148. NodePtr p;
  1149. int *moveMask, *visitMask;
  1150. {
  1151.   register NodePtr q, r;
  1152.   *moveMask = 0;
  1153.   *visitMask = 0;
  1154.   assert(p->tag == P_INVOC);
  1155.   q = p->b.invoc.args;
  1156.   Sequence_For(r, q)
  1157.     assert(r->tag == P_ARG);
  1158.     if (z__z > 31) ErrorMessage(p, "Implementation restriction 32 arguments");
  1159.     if (r->b.arg.move) (*moveMask) |= (1 << z__z);
  1160.     if (r->b.arg.visit) (*visitMask) |= (1 << z__z);
  1161.   Sequence_Next
  1162. }
  1163.  
  1164. Boolean isATrivialLiteral(p)
  1165. NodePtr p;
  1166. {
  1167.   register Tag t = p->tag;
  1168.   return(t == P_STRINGLIT ||
  1169.        t == P_CHARLIT ||
  1170.      t == P_INTLIT ||
  1171.      t == P_REALLIT ||
  1172.      t == P_BOOLLIT ||
  1173.      t == P_NILLIT ||
  1174.      t == P_BUILTINLIT);
  1175. }
  1176.  
  1177. void generateAssign(var, val)
  1178. NodePtr var, val;
  1179. {
  1180.   register Symbol st;
  1181.   Context c;
  1182.   st = ST_Fetch(var->b.symref.symbol);
  1183.   vPushVariable(st);
  1184.   c.kind = C_Variable;
  1185.   c.v = vTop();
  1186.   generateExpression(val, c);
  1187.   vGenerateAssign();
  1188.   assert(vEmpty());
  1189. }
  1190.  
  1191. void doMultipleAssigns(p)
  1192. register NodePtr p;
  1193. {
  1194.   register NodePtr q;
  1195.   assert(isASequence(p));
  1196.   Sequence_ReverseFor(q, p)
  1197.     assert(q->tag == P_SYMREF);
  1198.     vPushVariable(q->b.symref.symbol);
  1199.     vSwap();
  1200.     vGenerateAssign();
  1201.   Sequence_Next
  1202. }
  1203.  
  1204. void generateAssignStat(p)
  1205. NodePtr p;
  1206. {
  1207.   register NodePtr q;
  1208.   Variable result;
  1209.   OID id;
  1210.  
  1211.   assert(p->tag == P_ASSIGNSTAT);
  1212.   if (Sequence_Length(p->b.assignstat.left) == 0) {
  1213.     assert(Sequence_Length(p->b.assignstat.right) == 1);
  1214.     generateInvocation(p->b.assignstat.right->b.children[0], 0,
  1215.       anyContext);
  1216.   } else if (Sequence_Length(p->b.assignstat.right) == 1) {
  1217.     /*
  1218.      * We have either a simple assignment or a procedure call with multiple
  1219.      * results.
  1220.      */
  1221.     if (Sequence_Length(p->b.assignstat.left) == 1) {
  1222.       /*
  1223.        * Just a simple assignment.
  1224.        */
  1225.       generateAssign(p->b.assignstat.left->b.children[0],
  1226.     p->b.assignstat.right->b.children[0]);
  1227.     } else {
  1228.       /*
  1229.        * A procedure call with multiple results.
  1230.        */
  1231.       generateInvocation(p->b.assignstat.right->b.children[0],
  1232.     Sequence_Length(p->b.assignstat.left), anyContext);
  1233.       doMultipleAssigns(p->b.assignstat.left);
  1234.     }
  1235.   } else {
  1236.     /*
  1237.      * We have a multiple assignment statement.
  1238.      */
  1239.     assert(Sequence_Length(p->b.assignstat.left) ==
  1240.       Sequence_Length(p->b.assignstat.right));
  1241.     result.data = popper;
  1242.     result.abCon = popper;
  1243.     Sequence_For(q, p->b.assignstat.right)
  1244.       vPush(pusherContext.v);
  1245.       generateExpression(q, pusherContext);
  1246.       result.abCon = vTopAbCon();
  1247.       vGenerateAssign();
  1248.       id = getDDAbstractType(result.abCon);
  1249.       result.abCon = popper;
  1250.       setDDAbstractType(result.abCon, id);
  1251.       vPush(result);
  1252.       TS_Push();
  1253.     Sequence_Next
  1254.     doMultipleAssigns(p->b.assignstat.left);
  1255.   }
  1256. }
  1257.  
  1258. /*
  1259.  * hasInitially returns true iff generateInitially actually generates any
  1260.  * code.
  1261.  */
  1262. extern Boolean isAManifestConstant();
  1263. static Boolean hasInitially(p)
  1264. NodePtr p;
  1265. {
  1266.   register NodePtr q;
  1267.   register Symbol st;
  1268.   assert(p->tag == P_OBLIT);
  1269.   if (p->b.oblit.monitor != NN) {
  1270.     if (! p->b.oblit.monitor->b.monitor.mayBeElided) return(TRUE);
  1271.     if (p->b.oblit.monitor->b.monitor.init != NN) return(TRUE);
  1272.   }
  1273.   Sequence_For(q, p->b.oblit.setq)
  1274.     st = ST_Fetch(q->b.setq.inner->b.symref.symbol);
  1275.     if (isARealImport(st, TRUE) && st->usedOutsideInitially) return(TRUE);
  1276.   Sequence_Next
  1277.   Sequence_For(q, p->b.oblit.decls)
  1278.     if (q->tag == P_VARDECL) return(TRUE);
  1279.     else if (q->tag == P_CONSTDECL) {
  1280.       st = ST_Fetch(q->b.constdecl.sym->b.symdef.symbol);
  1281.       if (! isAManifestConstant(st)) return(TRUE);
  1282.     } else {
  1283.       assert(FALSE);
  1284.     }
  1285.   Sequence_Next
  1286.   if (p->b.oblit.monitor != NN) {
  1287.     Sequence_For(q, p->b.oblit.monitor->b.monitor.decls)
  1288.       if (q->tag == P_VARDECL) return(TRUE);
  1289.       else if (q->tag == P_CONSTDECL) {
  1290.     st = ST_Fetch(q->b.constdecl.sym->b.symdef.symbol);
  1291.     if (! isAManifestConstant(st)) return(TRUE);
  1292.       } else {
  1293.     assert(FALSE);
  1294.       }
  1295.     Sequence_Next
  1296.   }
  1297.   if (getCodeOID(p) == OIDOfBuiltin(B_INSTCT, CONDITIONINDEX)) return(TRUE);
  1298.   return(FALSE);
  1299. }
  1300.  
  1301. void generateInitially(p)
  1302. NodePtr p;
  1303. {
  1304.   AllocationInfoPtr initaip;
  1305.  
  1306.   assert(p->tag == P_OBLIT);
  1307.   initaip = fetchAllocationInfo((NodePtr) ((int)p + 1));
  1308.  
  1309.   initializeTemplate("L_initiallyTemplate", nextObjectNumber, TRUE);
  1310.   generateTemplate(initaip);
  1311.   emit("L_initiallyEP:\n");
  1312.   lineNumberComment(p);
  1313.   /*
  1314.    * Generate the enter operation code.
  1315.    */
  1316.  
  1317.   TS_startOperation(initaip, nextObjectNumber, 10001);
  1318.   
  1319.   generate(p->b.oblit.setq);
  1320.   generate(p->b.oblit.decls);
  1321.   if (p->b.oblit.monitor != NN) {
  1322.     /* initialize the monitor */
  1323.     generateMonInit();
  1324.     generate(p->b.oblit.monitor->b.monitor.decls);
  1325.     generate(p->b.oblit.monitor->b.monitor.init);
  1326.   }
  1327.   if (getCodeOID(p) == OIDOfBuiltin(B_INSTCT, CONDITIONINDEX)) {
  1328.     emitMove(buildRegisterDDNC(regs_b), buildRegisterDDNC(regs_arg1), 'l');
  1329.     generateKernelCall("em_condInit");
  1330.   }
  1331.   TS_endOperation(FALSE, TRUE, FALSE);
  1332.   freeAllRegs();
  1333. }
  1334.  
  1335. void generateProcess(p)
  1336. NodePtr p;
  1337. {
  1338.   AllocationInfoPtr aip;
  1339.   register NodePtr child;
  1340.   if (p == NN) return;
  1341.   assert(p->tag == P_PROCESSDEF || p->tag == P_COMP);
  1342.   if (p->tag == P_PROCESSDEF) {
  1343.     aip = fetchAllocationInfo(p);
  1344.   } else {
  1345.     assert(p->tag == P_COMP);
  1346.     if (!doGenerateCode) {
  1347.       aip = allocateAllocationInfo(p+1);
  1348.       aip->isActivation = TRUE;
  1349.       aip->scope = p;
  1350.       aip->invokeQueueSize = sizeof(InvokeQueue);
  1351.     } else {
  1352.       aip = fetchAllocationInfo(p+1);
  1353.     }
  1354.   }
  1355.  
  1356.   initializeTemplate("L_processTemplate", nextObjectNumber, FALSE);
  1357.   generateTemplate(aip);
  1358.   emit("L_processEP:\n");
  1359.   lineNumberComment(p);
  1360.   TS_startOperation(aip, nextObjectNumber, 10003);
  1361.   if (p->tag == P_PROCESSDEF) {
  1362.     assert(aip->parameterSize == 0);
  1363.     doChildren(p);
  1364.   } else {
  1365.     generate(p->b.comp.consts);
  1366.   }
  1367.   TS_endOperation(FALSE, FALSE, FALSE);
  1368. }
  1369.  
  1370. void generateRecovery(p)
  1371. NodePtr p;
  1372. {
  1373.   AllocationInfoPtr aip;
  1374.   register NodePtr child;
  1375.   if (p == NN) return;
  1376.   assert(p->tag == P_RECOVERYDEF);
  1377.   aip = fetchAllocationInfo(p);
  1378.  
  1379.   initializeTemplate("L_recoveryTemplate", nextObjectNumber, TRUE);
  1380.   generateTemplate(aip);
  1381.   emit("L_recoveryEP:\n");
  1382.   lineNumberComment(p);
  1383.   TS_startOperation(aip, nextObjectNumber, 10002);
  1384.   assert(aip->parameterSize == 0);
  1385.   doChildren(p);
  1386.   TS_endOperation(FALSE, FALSE, TRUE);
  1387. }
  1388.  
  1389. LoopRecordPtr loops = NULL;
  1390.  
  1391. extern void setHasInvokeQueueBit();
  1392.  
  1393. void generateTemplate(aip)
  1394. AllocationInfoPtr aip;
  1395. {
  1396.   /*
  1397.    * We know that the borings and locals do not have ab/cons, or else they
  1398.    * would not be boring or local.  The globals have ab/cons.  The order,
  1399.    * is monitor, borings, locals, globals in increasing offset order.
  1400.    * For data areas this is increasing address order, and for activation records
  1401.    * this is decreasing address order.
  1402.    */
  1403.   int i, low1, high1, low2, high2, newi;
  1404.   register NodePtr q;
  1405.   register Symbol st;
  1406.   
  1407.   nResultMoves = 0;
  1408.   if (aip == NULL) return;
  1409.   if (aip->isDataArea) {
  1410.     assert(! aip->isActivation);
  1411.     assert(aip->parameterSize == 0);
  1412.     assert(aip->resultSize == 0);
  1413.     assert(aip->invokeQueueSize == 0);
  1414.     if (aip->monitorSize != 0) {
  1415.       assert(aip->monitorSize == 8);
  1416.       saveShortStaticTemplate(MonitorBrand, IsNotParam, DataBrand, 1, FALSE);
  1417.     }
  1418.     if (aip->boringSize > 0) {
  1419.       assert(aip->boringSize % 4 == 0);
  1420.       saveShortStaticTemplate(DataBrand, IsNotParam, DataBrand,
  1421.     aip->boringSize, FALSE);
  1422.     }
  1423.     if (aip->localSize > 0) {
  1424.       assert(aip->localSize % 4 == 0);
  1425.       saveShortStaticTemplate(ODPBrand, IsNotParam, DataBrand,
  1426.     aip->localSize / 4, FALSE);
  1427.     }
  1428.     if (aip->attachedLocalSize > 0) {
  1429.       assert(aip->attachedLocalSize % 4 == 0);
  1430.       saveShortStaticTemplate(ODPBrand, IsNotParam, DataBrand,
  1431.     aip->attachedLocalSize / 4, TRUE);
  1432.     }
  1433.     if (aip->globalSize > 0) {
  1434.       assert(aip->globalSize % 8 == 0);
  1435.       saveShortStaticTemplate(VariableBrand, IsNotParam, DataBrand,
  1436.     aip->globalSize / 8, FALSE);
  1437.     }
  1438.     if (aip->attachedGlobalSize > 0) {
  1439.       assert(aip->attachedGlobalSize % 8 == 0);
  1440.       saveShortStaticTemplate(VariableBrand, IsNotParam, DataBrand,
  1441.     aip->attachedGlobalSize / 8, TRUE);
  1442.     }
  1443.   } else if (aip->isActivation) {
  1444.     assert(! aip->isDataArea);
  1445.     assert(aip->monitorSize == 0);
  1446.     Sequence_For(q, aip->resultList)
  1447.       st = q->b.symdef.symbol;
  1448.       assert(st->itsKind == ST_Result);
  1449.       if (st->isMove) nResultMoves++;
  1450.       saveShortStaticTemplate(VariableBrand,
  1451.     (ParamInfo)(st->isMove ? IsMoveResult : IsResult),
  1452.     DataBrand, 1, st->isAttached);
  1453.     Sequence_Next
  1454.     Sequence_For(q, aip->paramList)
  1455.       st = q->b.symdef.symbol;
  1456.       assert(st->itsKind == ST_Param);
  1457.       saveShortStaticTemplate(VariableBrand, IsArgument, DataBrand, 1,
  1458.     st->isAttached);
  1459.     Sequence_Next
  1460.     if (aip->invokeQueueSize > 0) {
  1461.       assert(aip->invokeQueueSize % sizeof(InvokeQueue) == 0);
  1462.       saveShortStaticTemplate(InvokeQueueBrand, IsNotParam, DataBrand,
  1463.     aip->invokeQueueSize / 8, FALSE);
  1464.       setHasInvokeQueueBit(TRUE);
  1465.     }
  1466.     if (aip->boringSize > 0) {
  1467.       assert(aip->boringSize % 4 == 0);
  1468.       saveShortStaticTemplate(DataBrand, IsNotParam, DataBrand,
  1469.     aip->boringSize, FALSE);
  1470.     }
  1471.     if (aip->localSize > 0) {
  1472.       assert(aip->localSize % 4 == 0);
  1473.       saveShortStaticTemplate(ODPBrand, IsNotParam, DataBrand,
  1474.     aip->localSize / 4, FALSE);
  1475.     }
  1476.     if (aip->attachedLocalSize > 0) {
  1477.       assert(aip->attachedLocalSize % 4 == 0);
  1478.       saveShortStaticTemplate(ODPBrand, IsNotParam, DataBrand,
  1479.     aip->attachedLocalSize / 4, TRUE);
  1480.     }
  1481.     if (aip->globalSize > 0) {
  1482.       assert(aip->globalSize % 8 == 0);
  1483.       saveShortStaticTemplate(VariableBrand, IsNotParam, DataBrand,
  1484.     aip->globalSize / 8, FALSE);
  1485.     }
  1486.     if (aip->attachedGlobalSize > 0) {
  1487.       assert(aip->attachedGlobalSize % 8 == 0);
  1488.       saveShortStaticTemplate(VariableBrand, IsNotParam, DataBrand,
  1489.     aip->attachedGlobalSize / 8, TRUE);
  1490.     }
  1491.     IFOPTION(allocateregisters, 1) {
  1492.       low1 = low2 = high1 = high2 = -1;
  1493.       for (i = 0; i < NALLOCATABLE; i++) {
  1494.     newi = i;
  1495.     if (aip->regs[i].isAllocated) {
  1496.       switch (aip->regs[i].itsKind) {
  1497.         case AK_Boring:
  1498.           saveRegisterTemplate(DataBrand, InRegister, MINALLOCATABLE+i, 1,
  1499.         FALSE);
  1500.           break;
  1501.         case AK_Local:
  1502.           saveRegisterTemplate(ODPBrand, InRegister, MINALLOCATABLE+i, 1,
  1503.         FALSE);
  1504.           break;
  1505.         case AK_AttachedLocal:
  1506.           saveRegisterTemplate(ODPBrand, InRegister, MINALLOCATABLE+i, 1,
  1507.         TRUE);
  1508.           break;
  1509.         case AK_Global:
  1510.           saveRegisterTemplate(VariableBrand, InRegister, MINALLOCATABLE+i,
  1511.         1, FALSE);
  1512.           newi++;
  1513.           break;
  1514.         case AK_AttachedGlobal:
  1515.           saveRegisterTemplate(VariableBrand, InRegister, MINALLOCATABLE+i,
  1516.         1, TRUE);
  1517.           newi++;
  1518.           break;
  1519.         default:
  1520.           assert(FALSE);
  1521.           break;
  1522.       }
  1523.       if (low1 == -1) {
  1524.         low1 = i;
  1525.         high1 = newi;
  1526.       } else if (high1 == i-1) {
  1527.         high1 = newi;
  1528.       } else if (low2 == -1) {
  1529.         low2 = i;
  1530.         high2 = newi;
  1531.       } else if (high2 == i-1) {
  1532.         high2 = newi;
  1533.       } else {
  1534.         assert(FALSE);
  1535.       }
  1536.       i = newi;
  1537.     }
  1538.       }
  1539.       if (low1 != -1) {
  1540.     saveRegisterTemplate(DataBrand, InSaveArea, MINALLOCATABLE + low1,
  1541.       high1 - low1 + 1, FALSE);
  1542.       }
  1543.       if (low2 != -1) {
  1544.     saveRegisterTemplate(DataBrand, InSaveArea, MINALLOCATABLE + low2,
  1545.       high2 - low2 + 1, FALSE);
  1546.       }
  1547. #ifdef vax
  1548.       assert(low2 == -1);
  1549. #endif
  1550.     }
  1551.   } else {
  1552.     assert(FALSE);
  1553.   }
  1554. }
  1555.  
  1556. extern Boolean easyGenerateObject();
  1557. extern char *writeAT();
  1558.  
  1559. void generateATObject(at)
  1560. NodePtr at;
  1561. {
  1562.   /*
  1563.    * This needs to build the code at like thingy, that has as its value
  1564.    * some stuff so that we can perform type checking at run-time.
  1565.    * Note that we also need to add to each Code at some stuff so that we 
  1566.    * can do type checking at run-time.
  1567.    */
  1568.   register NodePtr p, q;
  1569.   ODTag myTag;
  1570.   int index;
  1571.   Boolean hasNoPointer, immutable;
  1572.   char *codeName, *ATInfo, *sourceFileName;
  1573.   int codeNameLabel, ATInfoLabel, sourceFileNameLabel;
  1574.  
  1575.   if (easyGenerateObject(at, at->b.atlit.id, 0)) {
  1576.     nextObjectNumber++;
  1577.     return;
  1578.   }
  1579.   emit(
  1580.     " %c Copyright 1986 Eric Jul and Norm Hutchinson.  May not be used\n",
  1581.     COMMENTCHAR);
  1582.   emit(
  1583.     " %c for any purpose without written permission from the authors.\n",
  1584.     COMMENTCHAR);
  1585. #ifdef vax
  1586.   emit("\t.data\n");
  1587. #endif
  1588. #ifdef sun
  1589.   emit("\t.text\n");
  1590. #endif
  1591.  
  1592.   assert(at->b.atlit.name != NULL);
  1593.   codeName = ST_SymbolName(at->b.atlit.name->b.symdef.symbol);
  1594.   Comment("Abstract type named %s", codeName);
  1595.   sourceFileName = at->tag == P_ATLIT && at->b.atlit.sfname ? 
  1596.     at->b.atlit.sfname->b.stringlit.string : 
  1597.     currentFileName;
  1598.   Comment("Source file name %s", sourceFileName);
  1599.  
  1600.   emit("L_beginCDA:\n");
  1601.   inObject = TRUE;
  1602.  
  1603.   
  1604.   immutable = at->b.atlit.f.immutable;
  1605.   myTag = BuildTag(CodeTag, TRUE);        /* codeTag */
  1606.   if (at->b.atlit.id < (OID)0xff000100 && at->b.atlit.id > (OID)0xff000060) {
  1607.     /*
  1608.      * This is a builtin, and we need to be careful.
  1609.      */
  1610.     index = at->b.atlit.id & 0x1f;
  1611.     assert (index <= NUMBUILTINS);
  1612.     switch (index) {
  1613.       case BOOLEANINDEX:
  1614.       case CHARACTERINDEX:
  1615.       case INTEGERINDEX:
  1616.       case NILINDEX:
  1617.       case REALINDEX:
  1618.     hasNoPointer = TRUE;
  1619.     break;
  1620.       default:
  1621.     hasNoPointer = FALSE;
  1622.     break;
  1623.     }
  1624.     myTag.allInstancesAreLocal = immutable | hasNoPointer;
  1625.     myTag.hasNoPointer = hasNoPointer;
  1626.   } else {
  1627.     myTag.allInstancesAreLocal = immutable;
  1628.     myTag.hasNoPointer = FALSE;
  1629.   }
  1630.   writeTag(myTag);                /* codeTag */
  1631.   writeHexComment(at->b.atlit.id, "Code OID");    /* OID */
  1632.   currentCodeOID = at->b.atlit.id;
  1633.   writeHex(OIDOfBuiltin(B_INSTAT, SIGNATUREINDEX));
  1634.  
  1635.   writeHex((unsigned)EMVERSION);
  1636.                         /* code Name Offset */
  1637.   emit("\t.long\tL_codeName - L_beginCDA\n");
  1638.   emit("\t.long\tL_endCDA - L_beginCDA\n");    /* sizeOfThisCodeObject */
  1639.   writeData(0);                    /* instanceSize */
  1640.  
  1641. #ifdef BADCC
  1642.   writeTag(BuildTag(InvalidTag, immutable));    /* instanceTag */
  1643. #else
  1644.   {
  1645.     ODTag myTag;
  1646.     myTag = BuildTag(InvalidTag, immutable);
  1647.     writeTag(myTag);
  1648.   }
  1649. #endif BADCC
  1650.   writeData(0);                    /* ODATemplateOffset */
  1651.   writeData(0);                    /* ipMapOffset  */
  1652.  
  1653.   writeData(0);                    /* failureHandlerMapOffset */
  1654.   writeData(0);                    /* unavailableHandlerMapOffset */
  1655.   writeData(0);                    /* lineNumberMapOffset */
  1656.  
  1657.   if (Sequence_Length(at->b.atlit.ops) == 0) {
  1658.     writeData(0);
  1659.   } else {
  1660.     emit("\t.long\tL_opVectorStart - L_beginCDA\n");
  1661.   }
  1662.   emit("\t.long\tL_relocInfoStart - L_beginCDA\n"); /* relocationInfoOffset */
  1663.  
  1664.   emit("\t.long\tL_ATInfo - L_beginCDA\n");    /* at info offset */
  1665.  
  1666.   writeData(0);                    /* initiallyEP */
  1667.   writeData(0);                    /* initiallyTemplate */
  1668.   writeWord(0);
  1669.   writeWord(0);
  1670.   writeHex(0);
  1671.   writeData(0);                    /* recoveryEP */
  1672.   writeData(0);                    /* recoveryTemplate */
  1673.   writeWord(0);
  1674.   writeWord(0);
  1675.   writeHex(0);
  1676.   writeData(0);                    /* processEP */
  1677.   writeData(0);                    /* processTemplate */
  1678.   writeWord(0);
  1679.   writeWord(0);
  1680.   writeHex(0);
  1681.   emit("\t.long\tL_sourceFileName - L_beginCDA\n");
  1682.   writeWord(0);                /* ipMapOffset  */
  1683.  
  1684.   initializeRelocationInfo();
  1685.   debugStart();
  1686.   if (Sequence_Length(at->b.atlit.ops) != 0) {
  1687.     emit("L_opVectorStart:\n");
  1688.     writeData(Sequence_Length(at->b.atlit.ops));
  1689.     Sequence_For(p, at->b.atlit.ops)
  1690.       assert(p->tag == P_OPSIG);
  1691.       q = p->b.opsig.name;
  1692.       assert(q->tag == P_OPNAME);
  1693.       writeData(0);                /* entry point */
  1694.       writeData(0);                /* template offset */
  1695.       writeWord(Sequence_Length(p->b.opsig.params));
  1696.       writeWord(Sequence_Length(p->b.opsig.results));
  1697.       writeHex(q->b.opname.id);
  1698.     Sequence_Next
  1699.   }
  1700.  
  1701.   /* generate the AT info */
  1702.   ATInfo = writeAT(at, FALSE, TRUE);
  1703.   assert(ATInfo != NULL);
  1704.   ATInfoLabel = nextLabelNumber++;
  1705.   emitStringObject(ATInfo, ATInfoLabel, "ATInfo", nextObjectNumber);
  1706.  
  1707.   /* generate the code name */
  1708.   codeNameLabel = nextLabelNumber++;
  1709.   emitStringObject(codeName, codeNameLabel, "codeName", nextObjectNumber);
  1710.   /* generate the source file name */
  1711.   sourceFileNameLabel = nextLabelNumber++;
  1712.   emitStringObject(sourceFileName, sourceFileNameLabel, "sourceFileName",
  1713.     nextObjectNumber);
  1714.   debugDump();
  1715.  
  1716.   dumpRelocationInfo();
  1717.   
  1718.   emit("L_endCDA:\n");
  1719.  
  1720.   writeData(0);
  1721.   nextObjectNumber++;
  1722. }
  1723.  
  1724. void generateCodeObject(object, codeOID, monitorOps,
  1725.     nonMonOps, initially, recovery, process, doCreate, createOID)
  1726. OID codeOID, createOID;
  1727. NodePtr object, monitorOps, nonMonOps, initially, recovery, process;
  1728. Boolean doCreate;
  1729. {
  1730.   AllocationInfoPtr aip, initaip;
  1731.   register int i;
  1732.   register NodePtr ops, p, q;
  1733.   int stage, index;
  1734.   Boolean found, immutable, hasNoPointer, needsFunnyTemplate = FALSE;
  1735.   ODTag myTag;
  1736.   char *codeName, *sourceFileName;
  1737.   int codeNameLabel, sourceFileNameLabel;
  1738.   OID ownATOID;
  1739.   OID debugVectorInstanceATOID;
  1740.   int debugVectorSize;
  1741.  
  1742.   if (easyGenerateObject(object, codeOID, doCreate ? createOID : 0)) {
  1743.     nextObjectNumber++;
  1744.     return;
  1745.   }
  1746.   currentObject = object;
  1747.   nextOperationNumber = 0;
  1748.   emit(
  1749.     " %c Copyright 1986 Eric Jul and Norm Hutchinson.  May not be used\n",
  1750.     COMMENTCHAR);
  1751.   emit(
  1752.     " %c for any purpose without written permission from the authors.\n",
  1753.     COMMENTCHAR);
  1754. #ifdef vax
  1755.   emit("\t.data\n");
  1756. #endif
  1757. #ifdef sun
  1758.   emit("\t.text\n");
  1759. #endif
  1760.   codeName = object->tag == P_OBLIT ? 
  1761.     ST_SymbolName(object->b.oblit.name->b.symdef.symbol) :
  1762.     "Compilation";
  1763.   Comment("Code named %s", codeName);
  1764.   sourceFileName = object->tag == P_OBLIT && object->b.oblit.sfname ?
  1765.     object->b.oblit.sfname->b.stringlit.string :
  1766.     currentFileName;
  1767.   Comment("Source file name %s", sourceFileName);
  1768.  
  1769.   ownATOID = object->tag == P_OBLIT ? getID(object->b.oblit.myat) : 0;
  1770.  
  1771.   if (ownATOID != 0) ensureGenerate(ownATOID);
  1772.  
  1773.   emit("L_beginCDA:\n");
  1774.   inObject = TRUE;
  1775.   aip = fetchAllocationInfo(object);
  1776.  
  1777.   immutable = (object->tag == P_OBLIT && object->b.oblit.f.immutable);
  1778.   myTag = BuildTag(CodeTag, TRUE);        /* codeTag */
  1779.   if (codeOID < (OID)0xff000100 && codeOID > (OID)0xff000060) {
  1780.     /*
  1781.      * This is a builtin, and we need to be careful.
  1782.      */
  1783.     index = codeOID & 0x1f;
  1784.     assert (index <= NUMBUILTINS);
  1785.     switch (index) {
  1786.       case BOOLEANINDEX:
  1787.       case CHARACTERINDEX:
  1788.       case INTEGERINDEX:
  1789.       case NILINDEX:
  1790.       case REALINDEX:
  1791.     hasNoPointer = TRUE;
  1792.     break;
  1793.       case STRINGINDEX:
  1794.     hasNoPointer = FALSE;
  1795.     needsFunnyTemplate = TRUE;
  1796.     break;
  1797.       default:
  1798.     hasNoPointer = FALSE;
  1799.     break;
  1800.     }
  1801.     myTag.allInstancesAreLocal = immutable || hasNoPointer;
  1802.     myTag.hasNoPointer = hasNoPointer;
  1803.   } else {
  1804.     myTag.allInstancesAreLocal = immutable;
  1805.     myTag.hasNoPointer = FALSE;
  1806.   }
  1807.   IFTRACE(generate, 1) {
  1808.     if (!doGenerateCode) {
  1809.       printf("Generating code for object %s (0x%08x)\n", codeName, codeOID);
  1810.       IFTRACE(generate, 3) {
  1811.     if (object->tag == P_OBLIT) {
  1812.       printf("\timmutable = %s\n", object->b.oblit.f.immutable ? "true" : "false");
  1813.       printf("\tdoesNotDuplicateSelf = %s\n",
  1814.         object->b.oblit.f.doesNotDuplicateSelf ? "true" : "false");
  1815.       printf("\tdoesNotMoveArguments = %s\n",
  1816.         object->b.oblit.f.doesNotMoveArguments ? "true" : "false");
  1817.       printf("\tdoesNotMoveSelf = %s\n",
  1818.         object->b.oblit.f.doesNotMoveSelf ? "true" : "false");
  1819.     }
  1820.       }
  1821.     }
  1822.   }
  1823.  
  1824.   writeTag(myTag);                /* myTag */
  1825.   writeHexComment(codeOID, "Code OID");        /* OID */
  1826.   currentCodeOID = codeOID;
  1827.   writeHex(ownATOID);                /* own AT OID */
  1828.   writeHex((unsigned)EMVERSION);
  1829.                         /* code Name Offset */
  1830.   emit("\t.long\tL_codeName - L_beginCDA\n");
  1831.   emit("\t.long\tL_endCDA - L_beginCDA\n");    /* sizeOfThisCodeObject */
  1832.   if (object->tag == P_OBLIT && object->b.oblit.f.isVector) {
  1833.     /* the instance size of a vector is -1 */
  1834.     writeData(-1);
  1835.   } else if (object->tag == P_OBLIT && object->b.oblit.codeOID == OIDOfBuiltin(B_INSTCT, STRINGINDEX)) {
  1836.     /* the instance size of a string is also -1 */
  1837.     writeData(-1);
  1838.   } else {
  1839.     assert(aip->invokeQueueSize == 0);
  1840.     writeData(firstInstanceOffset + aip->boringSize + aip->localSize + 
  1841.       aip->attachedLocalSize + aip->globalSize +
  1842.       aip->attachedGlobalSize + aip->monitorSize +
  1843.       (immutable ? sizeof(OID) : 0));        /* instanceSize */
  1844.   }
  1845. #ifdef BADCC
  1846.   writeTag(BuildTag(GODataTag, immutable));    /* instanceTag */
  1847. #else
  1848.   {
  1849.     ODTag myTag;
  1850.     myTag  = BuildTag(GODataTag, immutable);
  1851.     writeTag(myTag);
  1852.   }
  1853. #endif BADCC
  1854.  
  1855.   emit("\t.long\tL_ODATemplate - L_beginCDA\n"); /* ODATemplateOffset */
  1856.   emit("\t.long\tL_IPMapStart - L_beginCDA\n");    /* ipMapOffset  */
  1857.  
  1858.   if (doGenerateCode) {
  1859.     if (mapHasEntries(failureHandlerMap)) {
  1860.       emit("\t.long\tL_failureHandlerMap - L_beginCDA\n"); /* failureHandlerMapOffset */
  1861.     } else {
  1862.       writeData(0);
  1863.     }
  1864.     if (mapHasEntries(unavailableHandlerMap)) {
  1865.       emit("\t.long\tL_unavailableHandlerMap - L_beginCDA\n"); /* unavailableHandlerMapOffset */
  1866.     } else {
  1867.       writeData(0);
  1868.     }
  1869.     if (mapHasEntries(lineNumberMap)) {
  1870.       emit("\t.long\tL_lineNumberMap - L_beginCDA\n"); /* lineNumberMapOffset */
  1871.     } else {
  1872.       writeData(0);
  1873.     }
  1874.   }
  1875.  
  1876.   if (monitorOps == NN && nonMonOps == NN) {
  1877.     writeData(0);
  1878.   } else {
  1879.     emit("\t.long\tL_opVectorStart - L_beginCDA\n");
  1880.   }
  1881.   emit("\t.long\tL_relocInfoStart - L_beginCDA\n"); /* relocationInfoOffset */
  1882.  
  1883.   writeHex(0);                    /* real code has no AT info */
  1884.  
  1885.   if (initially != NN) {
  1886.     emit("\t.long\tL_initiallyEP - L_beginCDA\n");    /* initiallyEP */
  1887.     emit("\t.long\tL_initiallyTemplate - L_beginCDA\n");/* initiallyTemplate */
  1888.     initaip = fetchAllocationInfo((NodePtr) ((int)initially + 1));
  1889.     assert(initaip->parameterSize % 8 == 0);
  1890.     assert(initaip->resultSize == 0);
  1891.     writeWord(initaip->parameterSize / 8);
  1892.     writeWord(0);
  1893.     writeHex(0);
  1894.   } else {
  1895.     writeData(0);                /* initiallyEP */
  1896.     writeData(0);                /* initiallyTemplate */
  1897.     writeWord(0);
  1898.     writeWord(0);
  1899.     writeHex(0);
  1900.   }
  1901.   if (recovery != NN) {
  1902.     emit("\t.long\tL_recoveryEP - L_beginCDA\n");    /* recoveryEP */
  1903.     emit("\t.long\tL_recoveryTemplate - L_beginCDA\n");    /* recoveryTemplate */
  1904.     writeWord(0);
  1905.     writeWord(0);
  1906.     writeHex(0);
  1907.   } else {
  1908.     writeData(0);                /* recoveryEP */
  1909.     writeData(0);                /* recoveryTemplate */
  1910.     writeWord(0);
  1911.     writeWord(0);
  1912.     writeHex(0);
  1913.   }
  1914.   if (process != NN) {
  1915.     emit("\t.long\tL_processEP - L_beginCDA\n");/* processEP */
  1916.     emit("\t.long\tL_processTemplate - L_beginCDA\n");    /* processTemplate */
  1917.     writeWord(0);
  1918.     writeWord(0);
  1919.     writeHex(0);
  1920.   } else {
  1921.     writeData(0);                /* processEP */
  1922.     writeData(0);                /* processTemplate */
  1923.     writeWord(0);
  1924.     writeWord(0);
  1925.     writeHex(0);
  1926.   }
  1927.   emit("\t.long\tL_sourceFileName - L_beginCDA\n");
  1928.   emit("\t.long\tL_debugInfoMap - L_beginCDA\n");    /* debugInfoMap*/
  1929.   debugStart();
  1930.   debugScope(1);
  1931.  
  1932.   initializeRelocationInfo();
  1933.   initializeTemplates();
  1934.   
  1935.   initializeTemplate("L_ODATemplate", nextObjectNumber, FALSE);
  1936.   if (object->tag == P_OBLIT && object->b.oblit.f.isVector) {
  1937.     Symbol st;
  1938.     Boolean isAttached = FALSE;
  1939.     AllocateKind ak;
  1940.     Brand instanceBrand;
  1941.     aip->boringSize = 0;
  1942.     aip->localSize = 0;
  1943.     aip->attachedLocalSize = 0;
  1944.     aip->globalSize = 0;
  1945.     aip->attachedGlobalSize = 0;
  1946.     aip->monitorSize = 0;
  1947.     aip->conditionSize = 0;
  1948.     if (object->b.oblit.codeOID == OIDOfBuiltin(B_INSTCT, BITCHUNKINDEX)) {
  1949.       instanceBrand = DataBrand;
  1950.       debugVectorSize = 4;
  1951.       debugVectorInstanceATOID = OIDOfBuiltin(B_INSTAT, INTEGERINDEX);
  1952.     } else {
  1953.       st = getElementTypeSymbol(object);
  1954.       isAttached = st->isAttached;
  1955.       ATCTToSizeAndKind(st->value.ATinfo, st->value.CTinfo, st->isAttached,
  1956.     &debugVectorSize, &ak);
  1957.       assert(debugVectorSize != 0);
  1958.       debugVectorInstanceATOID = OIDOf(st->value.ATinfo);
  1959.       if (ak == AK_Global) instanceBrand = VariableBrand;
  1960.       else if (ak == AK_Local) instanceBrand = ODPBrand;
  1961.       else if (ak == AK_Boring) instanceBrand = DataBrand;
  1962.       else assert(FALSE);
  1963.     }
  1964.     saveShortStaticTemplate(DataBrand, IsNotParam, DataBrand, 4, FALSE);
  1965.     saveShortStaticTemplate(VectorBrand, IsNotParam, instanceBrand, 1,
  1966.       isAttached);
  1967.   } else if (needsFunnyTemplate) {
  1968.     assert(index == STRINGINDEX);
  1969.     saveShortStaticTemplate(VectorBrand, IsNotParam, DataBrand, 1, FALSE);
  1970.   } else {
  1971.     generateTemplate(aip);
  1972.   }
  1973.  
  1974.   /* start of the executable code */
  1975.   emit("L_beginexecutable:\n");
  1976.   initializeMaps();
  1977.   /*
  1978.    * We need to be careful about the children, because declarations need 
  1979.    * to be in the initially section even if there isnt one.
  1980.    */
  1981.   if (monitorOps != NN || nonMonOps != NN) {
  1982.     for (i = 0, found = TRUE; found; i++) {
  1983.       found = FALSE;
  1984.       for (stage = 0; stage < 2 && !found; stage++) {
  1985.     if (stage == 0) {
  1986.       ops = monitorOps;
  1987.     } else if (stage == 1) {
  1988.       ops = nonMonOps;
  1989.     } 
  1990.     Sequence_For(p, ops)
  1991.       assert(p->tag == P_OPDEF);
  1992.       if (p->b.opdef.opNumber == i) {
  1993.         inMonitor = (stage == 0 && !p->b.opdef.isPrivate);
  1994.         generate(p);
  1995.         found = TRUE;
  1996.         break;
  1997.       }
  1998.     Sequence_Next
  1999.       }
  2000.     }
  2001.   }
  2002.  
  2003.   if (debugVectorSize) {
  2004.     debugVector(debugVectorInstanceATOID, debugVectorSize);
  2005.     debugVectorSize = 0;
  2006.   }
  2007.  
  2008.   if (initially != NN) generateInitially(initially);
  2009.   if (process != NN) generateProcess(process);
  2010.   if (recovery != NN) generateRecovery(recovery);
  2011.   finalizeMaps();
  2012.   debugScope(0);
  2013.   emit("L_endexecutable:\n");
  2014.  
  2015.   /* write the operation vector */
  2016.   emit(ALIGNDIRECTIVE);
  2017.   if (monitorOps != NN || nonMonOps != NN) {
  2018.     emit("L_opVectorStart:\n");
  2019.     writeData(nextOperationNumber);
  2020.     for (i = 0; i < nextOperationNumber; i++) {
  2021.       found = FALSE;
  2022.       for (stage = 0; stage < 2 && !found; stage++) {
  2023.     if (stage == 0) {
  2024.       ops = monitorOps;
  2025.     } else if (stage == 1) {
  2026.       ops = nonMonOps;
  2027.     } 
  2028.     Sequence_For(p, ops)
  2029.       assert(p->tag == P_OPDEF);
  2030.       if (p->b.opdef.opNumber == i) {
  2031.         q = p->b.opdef.sig;
  2032.         assert(q->tag == P_OPSIG);
  2033.         p = q->b.opsig.name;
  2034.         assert(p->tag == P_OPNAME);
  2035.         emit("\t.long\tL_operationEP_%d - L_beginCDA\n", i);
  2036.         emit(
  2037.           "\t.long\tL_operationTemplate_%d - L_beginCDA\n", i);
  2038.         writeWord(Sequence_Length(q->b.opsig.params));
  2039.         writeWord(Sequence_Length(q->b.opsig.results));
  2040.         writeHex(p->b.opname.id);
  2041.         found = TRUE;
  2042.         break;
  2043.       }
  2044.     Sequence_Next
  2045.       }
  2046.       assert(found);
  2047.     }
  2048.   }
  2049.  
  2050.   /* generate the code name */
  2051.   codeNameLabel = nextLabelNumber++;
  2052.   emitStringObject(codeName, codeNameLabel, "codeName", nextObjectNumber);
  2053.  
  2054.   /* generate the IP to template map */
  2055.   emit("L_IPMapStart:\n");
  2056. #ifdef vax
  2057.   emit("\t.long\tL_endexecutable - L_beginCDA - 1\n");
  2058. #endif
  2059. #ifdef sun
  2060.   emit("\t.long\tL_endexecutable - L_beginCDA - 2\n");
  2061. #endif
  2062.   emit("\t.long\tL_beginexecutable - L_beginCDA\n");
  2063.   for (i = 0; i < nextOperationNumber; i++) {
  2064.     emit("\t.long\tL_endoperation_%d - L_beginCDA\n", i);
  2065.     emit("\t.long\tL_operationTemplate_%d - L_beginCDA\n", i);
  2066.   }
  2067.   if (initially != NN) {
  2068.     emit("\t.long\tL_endoperation_%d - L_beginCDA\n", 10001);
  2069.     emit("\t.long\tL_initiallyTemplate - L_beginCDA\n");
  2070.   }
  2071.   if (recovery != NN) {
  2072.     emit("\t.long\tL_endoperation_%d - L_beginCDA\n", 10002);
  2073.     emit("\t.long\tL_recoveryTemplate - L_beginCDA\n");
  2074.   }
  2075.   if (process != NN) {
  2076.     emit("\t.long\tL_endoperation_%d - L_beginCDA\n", 10003);
  2077.     emit("\t.long\tL_processTemplate - L_beginCDA\n");
  2078.   }
  2079.  
  2080.   /* generate the source file name */
  2081.   sourceFileNameLabel = nextLabelNumber++;
  2082.   emitStringObject(sourceFileName, sourceFileNameLabel, "sourceFileName",
  2083.     nextObjectNumber);
  2084.  
  2085.   /* generate the failureHandlerMap */
  2086.   /* generate the unavailableHandlerMap */
  2087.   /* generate the lineNumberMapOffset */
  2088.   dumpMaps();
  2089.   debugDump();
  2090.  
  2091.   dumpStringLiterals();
  2092.   dumpVectorLiterals();
  2093.  
  2094.   dumpRelocationInfo();
  2095.   dumpTemplates();
  2096.   emit("L_endCDA:\n");
  2097.  
  2098.   if (doCreate != 0) {
  2099.     writeData(1);
  2100.     writeHexComment(createOID, "\t\t\tCreate OID");
  2101.   } else {
  2102.     writeData(0);
  2103.   }
  2104.   currentObject = NN;
  2105.   nextObjectNumber++;
  2106. }
  2107.  
  2108. extern NodePtr getCTInfo();
  2109.  
  2110. void generateResultAbCons(p)
  2111. register NodePtr p;
  2112. {
  2113.   register NodePtr q;
  2114.   register Symbol st;
  2115.   DD varAbCon, valAbCon;
  2116.   NodePtr ct;
  2117.  
  2118.   Sequence_For(q, p)
  2119.     assert(q->tag == P_PARAM);
  2120.     q = q->b.param.sym;
  2121.     assert(q->tag == P_SYMDEF);
  2122.     st = ST_Fetch(q->b.symdef.symbol);
  2123.     debugSymbol(st);
  2124.     if ((ct = getCTInfo(st)) != NULL) {
  2125.       varAbCon.kind = DD_Address;
  2126.       varAbCon.value.address = st->v.address;
  2127.       varAbCon = nextAddress(varAbCon);
  2128.       valAbCon = buildAbCon(getID(st->value.ATinfo),getCodeID(ct));
  2129.       emitMove(valAbCon, varAbCon, 'l');
  2130.     }
  2131.   Sequence_Next
  2132. }
  2133.  
  2134. fixDDView(source, target, oid, guaranteedWrong)
  2135. DD source, target;
  2136. OID oid;
  2137. Boolean guaranteedWrong;
  2138. {
  2139.   NodePtr at;
  2140.   DD kernelAbCon, variableAbOID, kernelAbOID, AbConAbOID;
  2141.   at = OTLookup(oid);
  2142.   assert(at->tag == P_ATLIT);
  2143.   if (Sequence_Length(at->b.atlit.ops) == 0) {
  2144.     /* we can use the existing at, since we won't do invokes */
  2145.     if (! isSameDD(source, target)) {
  2146.       emitMove(source, target, 'l');
  2147.     }
  2148.     return;
  2149.   }
  2150.   claimReg(regs_arg1, 1, ODPBrand);
  2151.   kernelAbCon = buildRegisterDD(regs_arg1);
  2152.  
  2153.   variableAbOID = buildManifestDD((int) oid);
  2154.   IFOPTION(view, 1) {
  2155.     claimReg(regs_arg2, 1, DataBrand);
  2156.   } else IFOPTION(view, 2) {
  2157.     claimReg(regs_arg2, 1, ODPBrand);
  2158.   } else {
  2159.     assert(FALSE);
  2160.   }
  2161.   kernelAbOID = buildRegisterDD(regs_arg2);
  2162.  
  2163.   emitMove(source, kernelAbCon, 'l');
  2164. #ifdef sun
  2165.   emit("\ttstl\t");
  2166.   writeDD(kernelAbCon, '\n');
  2167. #endif
  2168.   emit("\tj%s\t1f\n", JN(LSS));
  2169.   if (!guaranteedWrong) {
  2170.     AbConAbOID = increaseIndirection(kernelAbCon);
  2171.     AbConAbOID.value.address.offset = AbCon_ATOID;
  2172.     emit("\tcmpl\t");
  2173.     writeDD(variableAbOID, ',');
  2174.     writeDD(AbConAbOID, '\n');
  2175.     emit("\tj%s\t1f\n", JN(EQL));
  2176.   }
  2177.  
  2178.   IFOPTION(view, 1) {
  2179.     emitMove(variableAbOID, kernelAbOID, 'l');
  2180.     preemptReg(regs_scratch, 1);
  2181.     preemptReg(regs_arg3, 1);
  2182.     generateKernelCall("em_changeview");
  2183.   } else IFOPTION(view, 2) {
  2184.     variableAbOID.kind = DD_OIDToCodePtr;
  2185.     variableAbOID.value.id = oid;
  2186.     emitMove(variableAbOID, kernelAbOID, 'l');
  2187.     preemptReg(regs_scratch, 1);
  2188.     preemptReg(regs_arg3, 1);
  2189.     generateKernelCall("em_changeviewptr");
  2190.   } else {
  2191.     assert(FALSE);
  2192.   }
  2193.   freeDD(kernelAbOID);
  2194.   if (guaranteedWrong) {
  2195.     emitMove(kernelAbCon, target, 'l');
  2196.   } else if (isSameDD(source, target)) {
  2197.     emitMove(kernelAbCon, target, 'l');
  2198.     emit("1:\n");
  2199.   } else {
  2200.     emit("1:\n");
  2201.     emitMove(kernelAbCon, target, 'l');
  2202.   }    
  2203.   freeDD(kernelAbCon);
  2204.   ensureGenerate(oid);
  2205. }
  2206.  
  2207. void generateOneView(st)
  2208. register Symbol st;
  2209. {
  2210.   DD variableAbCon;
  2211.   if (getCTInfo(st) == NULL) {
  2212.     variableAbCon.kind = DD_Address;
  2213.     variableAbCon.value.address = st->v.address;
  2214.     variableAbCon = nextAddress(variableAbCon);
  2215.     fixDDView(variableAbCon, variableAbCon, getID(st->value.ATinfo), FALSE);
  2216.   }
  2217. }
  2218.  
  2219. void generateArgumentViews(p)
  2220. register NodePtr p;
  2221. {
  2222.   register NodePtr q;
  2223.   register Symbol st;
  2224.  
  2225.   Sequence_For(q, p)
  2226.     assert(q->tag == P_PARAM);
  2227.     q = q->b.param.sym;
  2228.     assert(q->tag == P_SYMDEF);
  2229.     st = ST_Fetch(q->b.symdef.symbol);
  2230.     debugSymbol(st);
  2231.     generateOneView(st);
  2232.   Sequence_Next
  2233. }
  2234.  
  2235. void ensureGenerate(id)
  2236. OID id;
  2237. {
  2238.   NodePtr p;
  2239.   OC_Stage stage;
  2240.  
  2241.   assert(id >= (OID)0xfe000000);
  2242.   p = OTLookup(id);
  2243.   assert((int)p != NIL);
  2244.   assert(p->tag == P_OBLIT || p->tag == P_ATLIT);
  2245.  
  2246.   if ((id & 0xffffff) <= (OID)0x000100) {
  2247.     if (bflag) {
  2248.       assert(thisBuiltin != NULL);
  2249.       assert(thisBuiltin->tag == P_OBLIT);
  2250.       if ((id & 0x1f) != (thisBuiltin->b.oblit.id & 0x1f)) {
  2251.     TRACE2(builtins, 1, "Not generating code for %s with id 0x%08x", ATName(p),
  2252.       id);
  2253.     return;
  2254.       }
  2255.     } else {
  2256.       return;
  2257.     }
  2258.   }
  2259.  
  2260.   stage = (OC_Stage) Map_Lookup(ocMap, (int) p);
  2261.   if ((int) stage == NIL) {
  2262.     Map_Insert(ocMap, (int) p, (int) OC_Scheduled);
  2263.     Sequence_Add(&ocStack, p);
  2264.     return;
  2265.   } else if (stage == OC_Done) {
  2266.     return;
  2267.   } else if (stage == OC_InProgress) {
  2268.     return;
  2269.   } else if (stage == OC_Scheduled) {
  2270.     return;
  2271.   } else assert(FALSE);
  2272. }
  2273. extern NodePtr theNode;
  2274.   
  2275. /* move exp to loc; fix exp at loc; unfix exp */
  2276. void generateLocationRequest(kernelCall, exp, loc)
  2277. char *kernelCall;
  2278. NodePtr exp, loc;
  2279. {
  2280.   lineNumberComment(exp);
  2281.   TS_StartInvocation();
  2282.   if (exp != NN) {
  2283.     vPush(pusherContext.v);
  2284.     generateExpression(exp, pusherContext);
  2285.     vGenerateAssign();
  2286.     TS_Push();
  2287.   }
  2288.   if (loc != NN) {
  2289.     generateExpression(loc, anyContext);
  2290.     moveVariableToRegisters(vPeek(0), regs_arg1);
  2291.     vDiscard();
  2292.   }
  2293.   preemptReg(regs_scratch, 1);
  2294.   preemptReg(regs_arg3, 1);
  2295.   TS_EndInvocation();
  2296.   generateKernelCall(kernelCall);
  2297. }
  2298.  
  2299. extern void newAssignTypes(), typeCheck();
  2300.  
  2301. NodePtr findLiteral(p)
  2302. register NodePtr p;
  2303. {
  2304.   NodePtr s, l;
  2305.   assert(p->tag == P_IFCLAUSE);
  2306.   p = p->b.ifclause.exp;
  2307.   assert(p->tag == P_INVOC);
  2308.   if (p->b.invoc.target->tag == P_SYMREF) {
  2309.     s = p->b.invoc.target;
  2310.     l = p->b.invoc.args->b.children[0]->b.arg.exp;
  2311.     p->b.invoc.target = l;
  2312.     p->b.invoc.args->b.children[0]->b.arg.exp = s;
  2313.   }
  2314.   p = p->b.invoc.target;
  2315.   assert(p->tag == P_INTLIT || p->tag == P_CHARLIT);
  2316.   return(p);
  2317. }
  2318.   
  2319. compareLiterals(pp, qp)
  2320. NodePtr *pp, *qp;
  2321. {
  2322.   NodePtr p = findLiteral(*pp), q = findLiteral(*qp);
  2323.   int l, r;
  2324.   if (p->tag == P_INTLIT) {
  2325.     l = atoi(p->b.intlit.string);
  2326.     r = atoi(q->b.intlit.string);
  2327.   } else {
  2328.     l = (int) p->b.charlit.string[0];
  2329.     r = (int) q->b.charlit.string[0];
  2330.   }
  2331.   return(l - r);
  2332. }
  2333.  
  2334. generateLabel(l, nl)
  2335. int l;
  2336. Boolean nl;
  2337. {
  2338.   emit("L_%d:%s", l, nl ? "\n" : "");
  2339. }
  2340.  
  2341. generateCaseTable(p, s, nArms, minArm, maxArm, literalTag)
  2342. NodePtr p;
  2343. Symbol s;
  2344. int nArms, minArm, maxArm;
  2345. Tag literalTag;
  2346. {
  2347.   int doneLabel, elseLabel, startLabel, nextLabel;
  2348.   int thisArm, nextArm;
  2349.   NodePtr r;
  2350.   Variable arg2, arg3, extra;
  2351.   DD symdd;
  2352.   startLabel =nextLabelNumber++;
  2353.   doneLabel = nextLabelNumber++;
  2354.   elseLabel = p->b.ifstat.elseclause ? nextLabelNumber++ : doneLabel;
  2355.   nextLabel = nextLabelNumber;
  2356.   nextLabelNumber += nArms;
  2357.   /*
  2358.    * This sorts the if clauses, and has the side effect of cleaning up the 
  2359.    * individual invocations.  Each is reordered so that the literal is the
  2360.    * target of the invocation.
  2361.    */
  2362.   qsort((char *)&(p->b.ifstat.ifclauses->b.children[0]),
  2363.     Sequence_Length(p->b.ifstat.ifclauses),
  2364.     sizeof(NodePtr),
  2365.     compareLiterals);
  2366.   /*
  2367.    * Generate the preliminary stuff.
  2368.    */
  2369.   symdd.kind = DD_Address;
  2370.   symdd.value.address = s->v.address;
  2371.   arg2.data  = buildRegisterDDNC(regs_arg2);
  2372.   arg2.abCon = buildConCon(INTEGERINDEX);
  2373.   arg3.data  = buildRegisterDDNC(regs_arg3);
  2374.   arg3.abCon = arg2.abCon;
  2375.   emitMove(symdd, arg2.data, 'l');
  2376. #ifdef sun
  2377.   if (minArm != 0) {
  2378.     emitMove(buildManifestDD(minArm), arg3.data, 'l');
  2379.     emit("\tsubl\t"); writeDD(arg3.data, ','); writeDD(arg2.data, '\n');
  2380.   }
  2381.   emitMove(buildManifestDD(maxArm - minArm), arg3.data, 'l');
  2382.   extra.data = generateCompare(&arg2, &arg3, 'l', GTRU);
  2383.   extra.abCon = buildConCon(BOOLEANINDEX);
  2384.   vPush(extra);
  2385.   generateBranch(TRUE, elseLabel);
  2386.   emit("\tmovw\tpc@(6,d0:l:2),d0\n");
  2387.   emit("\tjmp\tpc@(2,d0:w)\n");
  2388. #endif
  2389. #ifdef vax
  2390.   emit("\tcasel\t%s,$%d,$%d\n", RN(regs_arg2), minArm, maxArm-minArm);
  2391. #endif
  2392.   generateLabel(startLabel, TRUE);
  2393.   thisArm = minArm;
  2394.   Sequence_For(r, p->b.ifstat.ifclauses)
  2395.     switch (r->b.ifclause.exp->b.invoc.target->tag) {
  2396.       case P_INTLIT:
  2397.     nextArm = atoi(r->b.ifclause.exp->b.invoc.target->b.intlit.string);
  2398.     break;
  2399.       case P_CHARLIT:
  2400.     nextArm = (int)r->b.ifclause.exp->b.invoc.target->b.charlit.string[0];
  2401.     break;
  2402.     }
  2403.     if (nextArm < thisArm) continue;
  2404.     for (; thisArm < nextArm; thisArm++) {
  2405.       emit("\t.word\tL_%d-L_%d\n", elseLabel, startLabel);
  2406.     }
  2407.     emit("\t.word\tL_%d-L_%d\n", nextLabel + z__z, startLabel);
  2408.     thisArm++;
  2409.   Sequence_Next
  2410.   if (p->b.ifstat.elseclause) {
  2411.     generateLabel(elseLabel, TRUE);
  2412.     lineNumberComment(p->b.ifstat.elseclause);
  2413.     generate(p->b.ifstat.elseclause);
  2414.     emit("\tj%s\tL_%d\n", JN(ALWAYS), doneLabel);
  2415.     wroteCode = TRUE;
  2416.   } else {
  2417. #ifdef vax
  2418.   emit("\tj%s\tL_%d\n", JN(ALWAYS), doneLabel);
  2419. #endif
  2420.   }
  2421.   Sequence_For(r, p->b.ifstat.ifclauses)
  2422.     generateLabel(nextLabel++, TRUE);
  2423.     lineNumberComment(r->b.ifclause.stats);
  2424.     generate(r->b.ifclause.stats);
  2425.     if (z__z < Sequence_Length(p->b.ifstat.ifclauses) - 1) {
  2426.       emit("\tj%s\tL_%d\n", JN(ALWAYS), doneLabel);
  2427.       wroteCode = TRUE;
  2428.     }
  2429.   Sequence_Next
  2430.   generateLabel(doneLabel, TRUE);
  2431. }
  2432.  
  2433.  
  2434. Boolean tryToUseCaseStatement(p)
  2435. register NodePtr p;
  2436. {
  2437.   register NodePtr q, a1, a2, e, ct;
  2438.   Symbol s = NULL;
  2439.   static OID equalOID = 0;
  2440.   Boolean result = TRUE;
  2441.   Tag literalTag = T_NONE;
  2442.   int nArms = 0, thisLabel, minLabel, maxLabel;
  2443.  
  2444.   if (equalOID == 0) equalOID = ON_Translate("=");
  2445.   assert(p->tag == P_IFSTAT);
  2446.   Sequence_For(q, p->b.ifstat.ifclauses)
  2447.     assert(q->tag == P_IFCLAUSE);
  2448.     e = q->b.ifclause.exp;
  2449.     if (e->tag != P_INVOC) { result = FALSE; break; }
  2450.     if (e->b.invoc.opname->b.opname.id != equalOID) { result = FALSE; break; }
  2451.     a1 = e->b.invoc.target;
  2452.     if (Sequence_Length(e->b.invoc.args) != 1) { result = FALSE; break; }
  2453.     a2 = e->b.invoc.args->b.children[0];
  2454.     assert(a2->tag == P_ARG);
  2455.     a2 = a2->b.arg.exp;
  2456.     if (a1->tag != P_SYMREF) {
  2457.       NodePtr t;
  2458.       t = a1; a1 = a2; a2 = t;
  2459.     }
  2460.     if (a1->tag != P_SYMREF) { result = FALSE; break; }
  2461.     if (a2->tag != P_INTLIT && a2->tag != P_CHARLIT) { result = FALSE; break; }
  2462.     if (s != NULL && s != a1->b.symref.symbol) { result = FALSE; break; }
  2463.     if (literalTag != T_NONE && literalTag != a2->tag) {result=FALSE;break;}
  2464.     s = a1->b.symref.symbol;
  2465.     literalTag = a2->tag;
  2466.     nArms ++;
  2467.     switch (literalTag) {
  2468.       case P_INTLIT:
  2469.     thisLabel = atoi(a2->b.intlit.string);
  2470.     break;
  2471.       case P_CHARLIT:
  2472.     thisLabel = (int)a2->b.charlit.string[0];
  2473.     break;
  2474.       default:
  2475.     assert(FALSE);
  2476.     break;
  2477.     }
  2478.     if (nArms == 1 || thisLabel < minLabel) minLabel = thisLabel;
  2479.     if (nArms == 1 || thisLabel > maxLabel) maxLabel = thisLabel;
  2480.   Sequence_Next
  2481.   if (result) {
  2482.     ct = getCTInfo(s);
  2483.     if (ct == NULL) {
  2484.       result = FALSE;
  2485.     } else if (ct->b.oblit.codeOID == OIDOfBuiltin(B_INSTCT, INTEGERINDEX)) {
  2486.       if (literalTag != P_INTLIT) result = FALSE;
  2487.     } else if (ct->b.oblit.codeOID == OIDOfBuiltin(B_INSTCT, CHARACTERINDEX)) {
  2488.       if (literalTag != P_CHARLIT) result = FALSE;
  2489.     }
  2490.     if (nArms <= 2) result = FALSE;
  2491.     /* we want to check the range */
  2492.     if (nArms <= 10 && (double)(maxLabel - minLabel + 1) / nArms < 0.25) result = FALSE;
  2493.     if ((maxLabel - minLabel + 1) > 512 &&
  2494.     (double)(maxLabel - minLabel + 1) / nArms < 0.25) result = FALSE;
  2495.   }
  2496.   if (!result) return result;
  2497.   generateCaseTable(p, s, nArms, minLabel, maxLabel, literalTag);
  2498. }
  2499.  
  2500. void generate(p)
  2501. register NodePtr p;
  2502. {
  2503.   register NodePtr q, r, child;
  2504.   register Symbol st;
  2505.   OC_Stage stage;
  2506.   int label1;
  2507.   DD dd1, dd2;
  2508.   register Variable *v;
  2509.   AllocationInfoPtr aip;
  2510.   char buffer[256];
  2511.   static OID theCompilationOID;
  2512.   int endLabel, falseLabel, tendLabel;
  2513.  
  2514.   if ((int)p <= 0x200) return;
  2515.   theNode = p;
  2516.   switch (p->tag) {
  2517.     case P_COMP:
  2518.       doAllocate(p, doGenerateCode);
  2519.       if (!doGenerateCode) theCompilationOID = AllocateOID();
  2520.       generateCodeObject(p, theCompilationOID, NN, NN, NN, NN, p, TRUE, 0);
  2521.       break;
  2522.     case P_ATLIT:
  2523.       stage = (OC_Stage) Map_Lookup(ocMap, (int) p);
  2524.       if ((int) stage == NIL) {
  2525.     assert(inObject);
  2526.     Map_Insert(ocMap, (int) p, (int) OC_Scheduled);
  2527.     Sequence_Add(&ocStack, p);
  2528.     return;
  2529.       } else if (stage == OC_Done) {
  2530.     return;
  2531.       } else if (stage == OC_InProgress) {
  2532.     return;
  2533.       } else if (stage == OC_Scheduled && inObject) {
  2534.     return;
  2535.       } else {
  2536.     assert(stage == OC_Scheduled && ! inObject);
  2537.     inObject = TRUE;
  2538.       }
  2539.       if (! p->b.atlit.f.isManifest) {
  2540.     if (!doGenerateCode) nextObjectNumber++;
  2541.       } else {
  2542.     Map_Insert(ocMap, (int)p, OC_InProgress);
  2543.     if (! bflag && !p->b.atlit.f.typesAreAssigned) {
  2544.       TRACE1(delay, 1, "Need to assign types in %s", ATName(p));
  2545.       newAssignTypes(p, 1);
  2546.     }
  2547.     if (!bflag && !p->b.atlit.f.typesHaveBeenChecked) {
  2548.       TRACE1(delay, 1, "Need to type check %s", ATName(p));
  2549.       typeCheck(p);
  2550.     }
  2551.     doAllocate(p, doGenerateCode);
  2552.     generateATObject(p);
  2553.       }
  2554.       Map_Insert(ocMap, (int)p, OC_Done);
  2555.       break;
  2556.     case P_OBLIT:
  2557.       stage = (OC_Stage) Map_Lookup(ocMap, (int) p);
  2558.       if ((int) stage == NIL) {
  2559.     assert(inObject);
  2560.     Map_Insert(ocMap, (int) p, (int) OC_Scheduled);
  2561.     Sequence_Add(&ocStack, p);
  2562.     return;
  2563.       } else if (stage == OC_Done) {
  2564.     return;
  2565.       } else if (stage == OC_InProgress) {
  2566.     return;
  2567.       } else if (stage == OC_Scheduled && inObject) {
  2568.     return;
  2569.       } else {
  2570.     assert(stage == OC_Scheduled && ! inObject);
  2571.     inObject = TRUE;
  2572.       }
  2573.       if (p->b.oblit.f.isTypeVariable || p->b.oblit.f.dependsOnTypeVariable) {
  2574.     if (!doGenerateCode) nextObjectNumber++;
  2575.       } else {
  2576.     Map_Insert(ocMap, (int)p, OC_InProgress);
  2577.     if (!bflag && !p->b.atlit.f.typesAreAssigned) {
  2578.       TRACE1(delay, 1, "Need to assign types in %s", ATName(p));
  2579.       newAssignTypes(p, 1);
  2580.     }
  2581.     if (!bflag && !p->b.atlit.f.typesHaveBeenChecked) {
  2582.       TRACE1(delay, 1, "Need to type check %s", ATName(p));
  2583.       typeCheck(p);
  2584.     }
  2585.     doAllocate(p, doGenerateCode);
  2586.     generateCodeObject(p, getCodeOID(p),
  2587.       p->b.oblit.monitor == NN ? NN : p->b.oblit.monitor->b.monitor.ops,
  2588.       p->b.oblit.ops,    hasInitially(p) ? p : NN, 
  2589.       p->b.oblit.monitor==NN ? NN :p->b.oblit.monitor->b.monitor.recovery,
  2590.       p->b.oblit.process,
  2591.       p->b.oblit.f.writeSeparately,
  2592.       p->b.oblit.id);
  2593.       }
  2594.       Map_Insert(ocMap, (int)p, OC_Done);
  2595.       break;
  2596.     case P_SETQ:
  2597.       st = ST_Fetch(p->b.setq.inner->b.symref.symbol);
  2598.       if (isARealImport(st, TRUE)) {
  2599.     if (st->usedOutsideInitially) {
  2600.       Comment("Non-manifest setq of %s", ST_SymbolName(st));
  2601.       debugSymbol(p->b.setq.inner->b.symdef.symbol);
  2602.       generateAssign(p->b.setq.inner, p->b.setq.param);
  2603.       generateOneView(st);
  2604.     } else {
  2605.       Comment("Non-manifest not used outside initially setq of %s",
  2606.         ST_SymbolName(st));
  2607.       st->v.address = p->b.setq.param->b.symdef.symbol->v.address;
  2608.       generateOneView(ST_Fetch(p->b.setq.param->b.symdef.symbol));
  2609.     }
  2610.       } else {
  2611.     Comment("Manifest setq of %s", ST_SymbolName(st));
  2612.       }
  2613.       break;
  2614.     case P_VARDECL:
  2615.       st = ST_Fetch(p->b.vardecl.sym->b.symdef.symbol);
  2616.       if ((q = p->b.vardecl.value) != NN) {
  2617.     lineNumberComment(p);
  2618.       } else {
  2619.     q = nilNode;
  2620.       }
  2621.       IFOPTION(comment, 1) Comment("Var Decl \"%s\" (addr %s)", 
  2622.     ST_SymbolName(st),addressToString(st->v.address));
  2623.       debugSymbol(p->b.vardecl.sym->b.symdef.symbol);
  2624.       generateAssign(p->b.vardecl.sym, q);
  2625.       break;
  2626.     case P_CONSTDECL:
  2627.       st = ST_Fetch(p->b.constdecl.sym->b.symdef.symbol);
  2628.       if (isAManifestConstant(st)) {
  2629.     if (bflag && thisBuiltin == NULL) {
  2630.       thisBuiltin = st->value.value;
  2631.       TRACE1(builtins, 1, "This builtin is %s", ATName(thisBuiltin));
  2632.     }
  2633.     Comment("Manifest constant %s", ST_SymbolName(st));
  2634.     ensureGenerate(getID(st->value.value));
  2635.       } else {
  2636.     lineNumberComment(p);
  2637.     IFOPTION(comment, 1) Comment("Const Decl \"%s\" (addr %s)", 
  2638.       ST_SymbolName(st), addressToString(st->v.address));
  2639.     debugSymbol(p->b.constdecl.sym->b.symdef.symbol);
  2640.     generateAssign(p->b.constdecl.sym, p->b.constdecl.value);
  2641.       }
  2642.       break;
  2643.     case P_WHEREWIDGIT:
  2644.       if (p->b.wherewidgit.op == OCONFORMSTO) {
  2645.       } else {
  2646.     lineNumberComment(p);
  2647.     st = ST_Fetch(p->b.wherewidgit.sym->b.symdef.symbol);
  2648.     if (st->isManifest) {
  2649.       generateAssign(p->b.wherewidgit.sym, st->value.value);
  2650.     } else {
  2651.       generateAssign(p->b.wherewidgit.sym, p->b.wherewidgit.type);
  2652.     }
  2653.       }
  2654.       break;
  2655.     case P_UNAVAILABLEHANDLER:
  2656.     case P_FAILUREHANDLER:
  2657.       break;
  2658.     case P_BLOCK:
  2659.       blockStart(p);
  2660.       debugScope(1);
  2661.       generate(p->b.block.stats);
  2662.       debugScope(0);
  2663.       blockEnd();
  2664.       break;
  2665.     case P_OPDEF:
  2666.       aip = fetchAllocationInfo(p);
  2667.       Comment("Operation Definition %s", 
  2668.     ON_Name(p->b.opdef.sig->b.opsig.name->b.opname.id));
  2669.       debugScope(1);
  2670.       sprintf(buffer, "L_operationTemplate_%d", p->b.opdef.opNumber);
  2671.       initializeTemplate(buffer, 0, inMonitor);
  2672.       generateTemplate(aip);
  2673.       emit("L_operationEP_%d:\n", p->b.opdef.opNumber);
  2674.       lineNumberComment(p);
  2675.       wroteCode = TRUE;
  2676.       TS_startOperation(aip, nextObjectNumber, p->b.opdef.opNumber);
  2677.       if (gmflag && doGenerateCode) {
  2678.     while (nResultMoves--) INC(cEM_callByResultMoves);
  2679.       }
  2680.       /* check for mustBeCompilerExecuted */
  2681.       if (p->b.opdef.sig->b.opsig.mustBeCompilerExecuted) {
  2682.     generateKernelCall("em_assertionFailure");
  2683.       } else {
  2684.     /* check on monitor entry */
  2685.     if (inMonitor) {
  2686.       assert(p->b.opdef.isMonitored);
  2687.       generateMonEntry();
  2688.     }
  2689.     generateArgumentViews(p->b.opdef.sig->b.opsig.params);
  2690.     generateResultAbCons(p->b.opdef.sig->b.opsig.results);
  2691.     generate(p->b.opdef.body);
  2692.       }
  2693.       TS_endOperation(inMonitor, FALSE, FALSE);
  2694.       debugScope(0);
  2695.       nextOperationNumber ++;
  2696.       freeAllRegs();
  2697.       break;
  2698.     case P_INITDEF:
  2699.       debugScope(1);
  2700.       generate(p->b.initdef.body);
  2701.       debugScope(0);
  2702.       break;
  2703.     case P_OPSIG:
  2704.       doChildren(p);
  2705.       break;
  2706.     case P_PRIMSTAT:
  2707.       lineNumberComment(p);
  2708.       generatePrimitive(p);
  2709.       assert(vEmpty());
  2710.       break;
  2711.     case P_GLOBALREF:
  2712.       resolveGlobal(p, (ValuePtr) NULL);
  2713.       q = p->b.globalref.value;
  2714.       generate(q);
  2715.       break;
  2716.     case P_INVOC:
  2717.       assert(FALSE);
  2718.       break;
  2719.     case P_WAITSTAT:
  2720.       lineNumberComment(p);
  2721.       generateExpression(p->b.waitstat.exp, anyContext);
  2722.       v = vPeek(0);
  2723.       claimReg(regs_arg2, 1, ODPBrand);
  2724.       dd1 = buildRegisterDD(regs_arg2);
  2725.       emitMove(v->data, dd1, 'l');
  2726.       vDiscard();
  2727.       dd1.kind = DD_Address;
  2728.       dd1.value.address = nullAddress;
  2729.       dd1.value.address.base = Global;
  2730.       dd1.value.address.offset = firstInstanceOffset;
  2731.       if (currentObject->b.oblit.f.immutable)
  2732.     dd1.value.address.offset += sizeof(OID);
  2733.       claimReg(regs_arg1, 1, AddrBrand);
  2734.       dd2 = buildRegisterDD(regs_arg1);
  2735.       emitMoveAddress(dd1, dd2);
  2736.       preemptReg(regs_scratch, 1);
  2737.       preemptReg(regs_arg3, 1);
  2738.       generateKernelCall("em_condWait");
  2739.       freeReg(regs_arg1, 2);
  2740.       assert(vEmpty());
  2741.       break;
  2742.     case P_SIGNALSTAT:
  2743.       lineNumberComment(p);
  2744.       generateExpression(p->b.signalstat.exp, anyContext);
  2745.       v = vPeek(0);
  2746.       claimReg(regs_arg2, 1, ODPBrand);
  2747.       dd2 = buildRegisterDD(regs_arg2);
  2748.       emitMove(v->data, dd2, 'l');
  2749.       vDiscard();
  2750.       dd1.kind = DD_Address;
  2751.       dd1.value.address = nullAddress;
  2752.       dd1.value.address.base = Global;
  2753.       dd1.value.address.offset = firstInstanceOffset;
  2754.       if (currentObject->b.oblit.f.immutable)
  2755.     dd1.value.address.offset += sizeof(OID);
  2756.       claimReg(regs_arg1, 1, AddrBrand);
  2757.       dd2 = buildRegisterDD(regs_arg1);
  2758.       emitMoveAddress(dd1, dd2);
  2759.       preemptReg(regs_scratch, 1);
  2760.       preemptReg(regs_arg3, 1);
  2761.       if (p->b.signalstat.useSignalAndExit) {
  2762.     generateKernelCall("em_condSignalAndExit");
  2763.     emit("\tj%s\tL_operationreturnnomonexit_%d\n", JN(ALWAYS),
  2764.       nextOperationNumber);
  2765.       } else {
  2766.     generateKernelCall("em_condSignal");
  2767.       }
  2768.       freeReg(regs_arg1, 2);
  2769.       assert(vEmpty());
  2770.       break;
  2771.     case P_CHECKPOINTSTAT:
  2772.       {
  2773.     int flag = 0;
  2774.     Variable v;
  2775.     NodePtr loc = p->b.checkpointstat.loc;
  2776.     lineNumberComment(p);
  2777.     TS_StartInvocation();
  2778.     if (p->b.checkpointstat.verb == (Token)T_NONE) {
  2779.       flag = CHECKPOINT_DEFAULT;
  2780.     } else if (p->b.checkpointstat.verb == KTO) {
  2781.       flag = CHECKPOINT_TO;
  2782.     } else if (p->b.checkpointstat.verb == KAT) {
  2783.       if (p->b.checkpointstat.loc == (NodePtr) KALL) {
  2784.         flag = CHECKPOINT_ATALL;
  2785.         loc = NN;
  2786.       } else {
  2787.         flag = CHECKPOINT_AT;
  2788.       }
  2789.     } else {
  2790.       assert(FALSE);
  2791.     }
  2792.     if (p->b.checkpointstat.confirm) flag = flag | CHECKPOINT_CONFIRM;
  2793.     v.data = buildManifestDD(flag);
  2794.     v.abCon = buildConCon(INTEGERINDEX);
  2795.     moveDataToRegister(&v, regs_arg1, DataBrand);
  2796.     if (loc == NN) loc = Construct(P_NILLIT, 0);
  2797.     generateExpression(loc, anyContext);
  2798.     moveVariableToRegisters(vPeek(0), regs_arg2);
  2799.     vDiscard();
  2800.     preemptReg(regs_scratch, 1);
  2801.     freeReg(regs_arg1, 1);
  2802.     TS_EndInvocation();
  2803.     generateKernelCall("em_checkpoint");
  2804.       }
  2805.       break;
  2806.     case P_RETURNSTAT:
  2807.       lineNumberComment(p);
  2808.       emit("\tj%s\tL_operationreturn_%d\n", JN(ALWAYS), opNumber);
  2809.       break;
  2810.     case P_RETURNANDFAILSTAT:
  2811.       lineNumberComment(p);
  2812.       if (inMonitor) generateMonExit();
  2813.       generateKernelCall("em_returnAndFail");
  2814.       break;
  2815.     case P_LOOPSTAT:
  2816.       debugScope(1);
  2817.       {
  2818.     LoopRecordPtr this = (LoopRecordPtr) malloc(sizeof(LoopRecord));
  2819.     label1 = nextLabelNumber++;
  2820.     this->label = nextLabelNumber++;
  2821.     this->enclosing = loops;
  2822.     loops = this;
  2823.     emit("L_%d:\n", label1);
  2824.     lineNumberComment(p);
  2825.     doChildren(p);
  2826. #ifdef vax
  2827.     emit("\tjlbc\t*$ _preemptFlag,L_%d\n", label1);
  2828. #endif
  2829. #ifdef sun
  2830.     emit("\ttstl\t_preemptFlag\n");
  2831.     emit("\tj%s\tL_%d\n", JN(EQL), label1);
  2832. #endif
  2833.     generateKernelCall("em_loopPreempt");
  2834.     emit("\tj%s\tL_%d\n", JN(ALWAYS), label1);
  2835.     emit("L_%d:\n", this->label);
  2836.     assert(loops == this);
  2837.     loops = this->enclosing;
  2838.     free((char *) this);
  2839.       }
  2840.       debugScope(0);
  2841.       assert(vEmpty());
  2842.       break;
  2843.     case P_EXITSTAT:
  2844.       lineNumberComment(p);
  2845.       if (p->b.exitstat.exp != NULL) {
  2846.     Variable *bool;
  2847.     generateExpression(p->b.exitstat.exp, pslContext);
  2848.     bool = vPeek(0);
  2849.     vForceToTemp(bool, TS_Stack);
  2850.     switch (bool->data.kind) {
  2851.       case DD_Address:
  2852.         emit("\ttstl\t");
  2853.         writeDD(bool->data, '\n');
  2854.         emit("\tj%s\tL_%d\n", JN(NEQ), loops->label);
  2855.         break;
  2856.       case DD_PSLCondition:
  2857.         emit("\t%sj%s\tL_%d\n", JF(bool->data.value.condition.isFloat),
  2858.           JN(bool->data.value.condition.psl), loops->label);
  2859.         break;
  2860.       case DD_Manifest:
  2861.         if (bool->data.value.manifest) {
  2862.           emit("\tj%s\tL_%d\n", JN(ALWAYS), loops->label);
  2863.         } else {
  2864.           /* no way to execute this code */
  2865.           return;
  2866.         }
  2867.         break;
  2868.       default:
  2869.         assert(FALSE);
  2870.         break;
  2871.     }
  2872.     vDiscard(); 
  2873.       } else {
  2874.     emit("\tj%s\tL_%d\n", JN(ALWAYS), loops->label);
  2875.       }
  2876.       assert(vEmpty());
  2877.       break;
  2878.     case P_ASSIGNSTAT:
  2879.       lineNumberComment(p);
  2880.       assert(p->b.assignstat.op == OASSIGN);
  2881.       generateAssignStat(p);
  2882.       assert(vEmpty());
  2883.       break;
  2884.     case P_ASSERTSTAT:
  2885.       lineNumberComment(p);
  2886.       {
  2887.     Variable *bool;
  2888.     label1 = nextLabelNumber++;
  2889.     generateExpression(p->b.assertstat.exp, pslContext);
  2890.     bool = vPeek(0);
  2891.     vForceToTemp(bool, TS_Stack);
  2892.     switch (bool->data.kind) {
  2893.       case DD_Address:
  2894.         emit("\ttstl\t%s\n", addressToString(bool->data.value.address));
  2895.         emit("\tj%s\tL_%d\n", JN(NEQ), label1);
  2896.         break;
  2897.       case DD_PSLCondition:
  2898.         emit("\t%sj%s\tL_%d\n", JF(bool->data.value.condition.isFloat),
  2899.           JN(bool->data.value.condition.psl), label1);
  2900.         break;
  2901.       case DD_Manifest:
  2902.         if (bool->data.value.manifest) {
  2903.           /* assert true */
  2904.           return;
  2905.         } else {
  2906.           /* assert false */
  2907.         }
  2908.         break;
  2909.       default:
  2910.         assert(FALSE);
  2911.         break;
  2912.     }
  2913.     generateKernelCall("em_assertionFailure");
  2914.     emit("L_%d:\n", label1);
  2915.     wroteCode = TRUE;
  2916.     vDiscard();
  2917.       }
  2918.       assert(vEmpty());
  2919.       break;
  2920.     
  2921.     case P_MOVESTAT:
  2922.       INC(cEM_moves);
  2923.       generateLocationRequest("em_move",p->b.movestat.exp, p->b.movestat.loc);
  2924.       break;
  2925.     case P_FIXSTAT:
  2926.       INC(cEM_fixes);
  2927.       generateLocationRequest("em_fix", p->b.fixstat.exp, p->b.fixstat.loc);
  2928.       break;
  2929.     case P_REFIXSTAT:
  2930.       INC(cEM_refixes);
  2931.       generateLocationRequest("em_refix", p->b.refixstat.exp, p->b.refixstat.loc);
  2932.       break;
  2933.     case P_UNFIXSTAT:
  2934.       INC(cEM_unfixes);
  2935.       generateLocationRequest("em_unfix", p->b.unfixstat.exp, NN);
  2936.       break;
  2937.     case P_IFSTAT:
  2938.       lineNumberComment(p);
  2939.       if (tryToUseCaseStatement(p)) break;
  2940.       endLabel = nextLabelNumber++;
  2941.       q = p->b.ifstat.ifclauses;
  2942.       Sequence_For(r, q)
  2943.     falseLabel = nextLabelNumber++;
  2944.     if (p->b.ifstat.elseclause == NN && z__z == q->nChildren-1) {
  2945.       tendLabel = 0;
  2946.     } else {
  2947.       tendLabel = endLabel;
  2948.     }
  2949.     generateIfClause(r, tendLabel, falseLabel);
  2950.     emit("L_%d:\n", falseLabel);
  2951.       Sequence_Next
  2952.       if (p->b.ifstat.elseclause != NULL) {
  2953.     lineNumberComment(p->b.ifstat.elseclause);
  2954.     debugScope(1);
  2955.     generate(p->b.ifstat.elseclause);
  2956.     debugScope(0);
  2957.       }
  2958.       emit("L_%d:\n", endLabel);
  2959.       assert(vEmpty());
  2960.       break;
  2961.     case P_IFCLAUSE:
  2962.       assert(FALSE);
  2963.       break;
  2964.     case P_ELSECLAUSE:
  2965.       generate(p->b.elseclause.stats);
  2966.       assert(vEmpty());
  2967.       break;
  2968.     case T_SEQUENCE:
  2969.       doChildren(p);
  2970.       break;
  2971.     default:
  2972.       emit("%s\n", tagNames[(int)p->tag]);
  2973.       doChildren(p);
  2974.       break;
  2975.   }
  2976. }
  2977.  
  2978. void generatePrimitive(p)
  2979. register NodePtr p;
  2980. {
  2981.   register NodePtr primno;
  2982.   int nargs, i;
  2983.   Variable vTarget, *target = &vTarget;
  2984.   Boolean hasResult = FALSE;
  2985.   Symbol st;
  2986.   Context resultContext;
  2987.  
  2988.   assert(p->tag == P_PRIMSTAT);
  2989.  
  2990.   target->data = buildRegisterDD(regs_g);
  2991.   target->abCon = buildAbConFromObject(currentObject);
  2992.   primno = p->b.primstat.number;
  2993.   if (Sequence_Length(p->b.primstat.vars) > 0) {
  2994.     assert(Sequence_Length(p->b.primstat.vars) == 1);
  2995.     st = ST_Fetch(p->b.primstat.vars->b.children[0]->b.symref.symbol);
  2996.     vPushVariable(st);
  2997.     hasResult = TRUE;
  2998.     resultContext.kind = C_Variable;
  2999.     resultContext.v = vTop();
  3000.   } else {
  3001.     resultContext = anyContext;
  3002.   }
  3003.   nargs = Sequence_Length(p->b.primstat.vals);
  3004.   for (i = 0; i < nargs; i++) {
  3005.     generateExpression(p->b.primstat.vals->b.children[i], anyContext);
  3006.   }
  3007.   /*
  3008.    * DoPrimitive leaves the result (if there is one) on the variable stack.
  3009.    */
  3010.   doPrimitive(currentObject, p, primno, target, nargs, hasResult,
  3011.     resultContext);
  3012.   if (hasResult) {
  3013.     vGenerateAssign();
  3014.   }
  3015. }
  3016.  
  3017. generateOneGuy(p)
  3018. NodePtr p;
  3019. {
  3020.   doGenerateCode = FALSE;
  3021.   nextLabelNumber = 101;
  3022.   generate(p);
  3023.   Map_Insert(ocMap, (int)p, OC_Scheduled);
  3024.   nextObjectNumber --;
  3025.   nextLabelNumber = 101;
  3026.   inObject = FALSE;
  3027.   doGenerateCode = TRUE;
  3028.   generate(p);
  3029. }
  3030.  
  3031. void generateCode(p)
  3032. NodePtr p;
  3033. {
  3034.   NodePtr q;
  3035.   assert(p->tag == P_COMP);
  3036.   inObject = TRUE;
  3037.   generateOneGuy(p);
  3038.   while (Sequence_Length(ocStack) > 0) {
  3039.     q = ocStack->b.children[ocStack->nChildren-1];
  3040.     ocStack->nChildren--;
  3041.     inObject = FALSE;
  3042.     generateOneGuy(q);
  3043.   }
  3044.   printStatistics();
  3045. }
  3046.  
  3047. printStatistics()
  3048. {
  3049.   if (!gmflag) return;
  3050.   TRACE1(passes, 1, "totalInvokes = %4d", cEM_totalInvokes);
  3051.   TRACE1(passes, 1, "directInvokes = %4d", cEM_directInvokes);
  3052.   TRACE1(passes, 1, "inlinedInvokes = %4d", cEM_inlinedInvokes);
  3053.   TRACE1(passes, 1, "localInvokes = %4d", cEM_localInvokes);
  3054.   TRACE1(passes, 1, "selfInvokes = %4d", cEM_selfInvokes);
  3055.   TRACE1(passes, 1, "KCTimmutableInvokes = %4d", cEM_KCTimmutableInvokes);
  3056.   TRACE1(passes, 1, "UKCTimmutableInvokes = %4d", cEM_UKCTimmutableInvokes);
  3057.   TRACE1(passes, 1, "KCTresidentGlobalInvokes = %4d",
  3058.     cEM_KCTresidentGlobalInvokes);
  3059.   TRACE1(passes, 1, "UKCTresidentGlobalInvokes = %4d",
  3060.     cEM_UKCTresidentGlobalInvokes);
  3061.   TRACE1(passes, 1, "moves = %4d", cEM_moves);
  3062.   TRACE1(passes, 1, "fixes = %4d", cEM_fixes);
  3063.   TRACE1(passes, 1, "unfixes = %4d", cEM_unfixes);
  3064.   TRACE1(passes, 1, "refixes = %4d", cEM_refixes);
  3065.   TRACE1(passes, 1, "locates = %4d", cEM_locates);
  3066.   TRACE1(passes, 1, "callByMoves = %4d", cEM_callByMoves);
  3067.   TRACE1(passes, 1, "callByVisits = %4d", cEM_callByVisits);
  3068.   TRACE1(passes, 1, "callByResultMoves = %4d", cEM_callByResultMoves);
  3069. }
  3070.